Skip to content

Conversation

@mfsiega
Copy link
Contributor

@mfsiega mfsiega commented Nov 21, 2025

Summary

Internally switch to use a structured DestinationNode by making RunExecutionDataV1 the default.

Externally, nothing changes - the controller still accepts the old format and passes mode: 'inclusive' to preserve the existing behaviour. The next PR will make the change in the API and frontend to actually fix the original bug.

This PR also adds code to migrate records to the latest version of RunExecutionData, and uses this to make sure we can still read old records in the database. It adds an e2e test to verify that this happens in the execution repository.

Finally, this PR also updates the various (many) places that handle the destination node to process the new structure.

Related Linear tickets, Github issues, and Community forum posts

https://linear.app/n8n/issue/CAT-1265

Review / Merge checklist

  • PR title and summary are descriptive. (conventions)
  • Docs updated or follow-up ticket created.
  • Tests included.
  • PR Labeled with release/backport (if the PR is an urgent fix that needs to be backported)

@mfsiega mfsiega changed the title switch to structured destination node feat(core): Switch to structured destination node (no-changelog) Nov 21, 2025
@n8n-assistant n8n-assistant bot added core Enhancement outside /nodes-base and /editor-ui n8n team Authored by the n8n team labels Nov 21, 2025
@bundlemon
Copy link

bundlemon bot commented Nov 21, 2025

BundleMon

Unchanged files (2)
Status Path Size Limits
WASM Dependencies
tree-sitter-bash.wasm
181.26KB -
WASM Dependencies
tree-sitter.wasm
74.47KB -

No change in files bundle size

Groups updated (2)
Status Path Size Limits
**/*.js
11.38MB (+94.65KB +0.82%) -
**/*.css
231.53KB (+10.76KB +4.87%) -

Final result: ✅

View report in BundleMon website ➡️


Current branch size history | Target branch size history

@codecov
Copy link

codecov bot commented Nov 21, 2025

@blacksmith-sh

This comment has been minimized.

@currents-bot
Copy link

currents-bot bot commented Nov 21, 2025

E2E Tests: n8n tests passed after 9m 1.7s

🟢 588 · 🔴 0 · ⚪️ 12 · 🟣 5

View Run Details

Run Details

  • Project: n8n

  • Groups: 2

  • Framework: Playwright

  • Run Status: Passed

  • Commit: 26a992d

  • Spec files: 96

  • Overall tests: 600

  • Duration: 9m 1.7s

  • Parallelization: 9

Groups

GroupId Results Spec Files Progress
ui 🟢 539 · 🔴 0 · ⚪️ 12 · 🟣 5 90 / 90
ui:isolated 🟢 49 · 🔴 0 · ⚪️ 0 6 / 6


This message was posted automatically by currents.dev | Integration Settings

@mfsiega mfsiega marked this pull request as ready for review November 21, 2025 14:56
@mfsiega mfsiega requested review from despairblue and tomi November 21, 2025 14:56
@mfsiega mfsiega marked this pull request as draft November 21, 2025 14:57
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cubic analysis

1 issue found across 25 files

Prompt for AI agents (all 1 issues)

Understand the root cause of the following 1 issues and fix them.


<file name="packages/cli/src/workflows/workflow-execution.service.ts">

<violation number="1" location="packages/cli/src/workflows/workflow-execution.service.ts:104">
Rule violated: **Tests**

Manual execution behavior is being rewritten to pass a structured destination node so that partial runs (per Linear issue CAT-1265) only execute the intended nodes, yet the PR adds no unit/workflow tests to demonstrate that this bug is fixed. The Community PR Guidelines explicitly require PRs to include tests, so this regression fix currently ships without the mandated coverage and risks the issue recurring.</violation>
</file>

Linked issue analysis

Linked issue: CAT-1265: Bug - Form node - executing previous nodes causes current node to run

Status Acceptance criteria Notes
⚠️ Executing previous nodes should not run the current node when in a 'next form step' node Added destination.mode & conditional include, but callers still default to inclusive

Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR

) {
const { workflowData, startNodes, dirtyNodeNames, triggerToStartFrom, agentRequest } = payload;
let { runData } = payload;
const destinationNode: IDestinationNode | undefined = payload.destinationNode
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rule violated: Tests

Manual execution behavior is being rewritten to pass a structured destination node so that partial runs (per Linear issue CAT-1265) only execute the intended nodes, yet the PR adds no unit/workflow tests to demonstrate that this bug is fixed. The Community PR Guidelines explicitly require PRs to include tests, so this regression fix currently ships without the mandated coverage and risks the issue recurring.

Prompt for AI agents
Address the following comment on packages/cli/src/workflows/workflow-execution.service.ts at line 104:

<comment>Manual execution behavior is being rewritten to pass a structured destination node so that partial runs (per Linear issue CAT-1265) only execute the intended nodes, yet the PR adds no unit/workflow tests to demonstrate that this bug is fixed. The Community PR Guidelines explicitly require PRs to include tests, so this regression fix currently ships without the mandated coverage and risks the issue recurring.</comment>

<file context>
@@ -92,26 +93,26 @@ export class WorkflowExecutionService {
 	) {
+		const { workflowData, startNodes, dirtyNodeNames, triggerToStartFrom, agentRequest } = payload;
+		let { runData } = payload;
+		const destinationNode: IDestinationNode | undefined = payload.destinationNode
+			? {
+					nodeName: payload.destinationNode,
</file context>
Fix with Cubic

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR intentionally does not fix the e2e behaviour. A subsequent PR will update the API, as well as add tests to verify that the mode is handled appropriately.

@mfsiega mfsiega marked this pull request as ready for review November 21, 2025 15:49
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 29 files

Prompt for AI agents (all 3 issues)

Understand the root cause of the following 3 issues and fix them.


<file name="packages/cli/src/events/relays/telemetry.event-relay.ts">

<violation number="1" location="packages/cli/src/events/relays/telemetry.event-relay.ts:790">
Remove the stray `console.log`—it dumps manual execution data (potentially sensitive) to stdout instead of using the structured telemetry/logging pipeline, which violates the style guidelines for production code.</violation>
</file>

<file name="packages/workflow/src/run-execution-data/run-execution-data.ts">

<violation number="1" location="packages/workflow/src/run-execution-data/run-execution-data.ts:35">
Rule violated: **Prefer Typeguards over Type casting**

`migrateRunExecutionData` now ends with a bare `as` cast, so the union `IRunExecutionDataAll` is forced into `IRunExecutionData` without a type guard or discriminant-based narrowing, violating the “Prefer Typeguards over Type casting” rule and hiding missing migrations.</violation>
</file>

<file name="packages/@n8n/db/src/repositories/execution.repository.ts">

<violation number="1" location="packages/@n8n/db/src/repositories/execution.repository.ts:221">
Rule violated: **Prefer Typeguards over Type casting**

The updated execution loaders still narrow the parsed payload with `parse(executionData.data) as IRunExecutionDataAll`, which violates the “Prefer type guards over type casting” rule. Introduce a typed variable or guard that proves the value matches `IRunExecutionDataAll` before calling `migrateRunExecutionData`, rather than asserting with `as`.</violation>
</file>

Reply to cubic to teach it or ask questions. Re-run a review with @cubic-dev-ai review this PR

// Fall through to subsequent versions as they're added.
}
// NOTE: it's safe to assert here because we have handled all previous versions.
return data as IRunExecutionData;
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rule violated: Prefer Typeguards over Type casting

migrateRunExecutionData now ends with a bare as cast, so the union IRunExecutionDataAll is forced into IRunExecutionData without a type guard or discriminant-based narrowing, violating the “Prefer Typeguards over Type casting” rule and hiding missing migrations.

Prompt for AI agents
Address the following comment on packages/workflow/src/run-execution-data/run-execution-data.ts at line 35:

<comment>`migrateRunExecutionData` now ends with a bare `as` cast, so the union `IRunExecutionDataAll` is forced into `IRunExecutionData` without a type guard or discriminant-based narrowing, violating the “Prefer Typeguards over Type casting” rule and hiding missing migrations.</comment>

<file context>
@@ -20,6 +20,17 @@ const __brand = Symbol(&#39;brand&#39;);
+		// Fall through to subsequent versions as they&#39;re added.
+	}
+	// NOTE: it&#39;s safe to assert here because we have handled all previous versions.
+	return data as IRunExecutionData;
+}
</file context>

✅ Addressed in db58367

return {
...rest,
data: parse(executionData.data) as IRunExecutionData,
data: migrateRunExecutionData(parse(executionData.data) as IRunExecutionDataAll),
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Nov 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rule violated: Prefer Typeguards over Type casting

The updated execution loaders still narrow the parsed payload with parse(executionData.data) as IRunExecutionDataAll, which violates the “Prefer type guards over type casting” rule. Introduce a typed variable or guard that proves the value matches IRunExecutionDataAll before calling migrateRunExecutionData, rather than asserting with as.

Prompt for AI agents
Address the following comment on packages/@n8n/db/src/repositories/execution.repository.ts at line 221:

<comment>The updated execution loaders still narrow the parsed payload with `parse(executionData.data) as IRunExecutionDataAll`, which violates the “Prefer type guards over type casting” rule. Introduce a typed variable or guard that proves the value matches `IRunExecutionDataAll` before calling `migrateRunExecutionData`, rather than asserting with `as`.</comment>

<file context>
@@ -217,7 +218,7 @@ export class ExecutionRepository extends Repository&lt;ExecutionEntity&gt; {
 				return {
 					...rest,
-					data: parse(executionData.data) as IRunExecutionData,
+					data: migrateRunExecutionData(parse(executionData.data) as IRunExecutionDataAll),
 					workflowData: executionData.workflowData,
 					customData: Object.fromEntries(metadata.map((m) =&gt; [m.key, m.value])),
</file context>
Fix with Cubic

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR doesn't change the behaviour here - we were always asserting. We trust that only IRunExecutionData (of some version) has been written to the database.

@blacksmith-sh

This comment has been minimized.

@blacksmith-sh

This comment has been minimized.

mfsiega and others added 17 commits November 21, 2025 20:51
Clarify the difference between inclusive and exclusive execution modes
for destination nodes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Remove unnecessary isRunExecutionDataV1 type guard
- Use direct version check instead
- Simplify type assertions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Add default value for options parameter
- Remove unnecessary type annotations (inferred by TypeScript)
- Use non-optional chaining with default parameter

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…rvice

TypeScript can infer the type from the ternary expression.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Mark that destinationNode field needs to be updated from string to
IDestinationNode to complete CAT-1265 properly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Refactor 3 test cases to use the proper factory function instead of
manually constructing error execution data. This makes tests more
maintainable and ensures consistent structure.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Add tests for both execution order versions (v0 and v1) to verify:
- Exclusive mode: destination node does not execute
- Inclusive mode: destination node executes

Also add tests for checkReadyForExecution to verify:
- Exclusive mode: destination node is not checked for issues
- Inclusive mode: destination node is checked for issues

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
despairblue
despairblue previously approved these changes Nov 24, 2025
Copy link
Contributor

@despairblue despairblue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made some small changes (adding tests, removing some types that can be inferred, adding a todo, etc.). Please check them out and let me know if you agree with them.

Rest look really good. Nice job!

@mfsiega mfsiega merged commit 9319139 into master Nov 24, 2025
41 checks passed
@mfsiega mfsiega deleted the cat-1265-dont-run-destination-node5 branch November 24, 2025 15:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core Enhancement outside /nodes-base and /editor-ui n8n team Authored by the n8n team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants