Repository: n8n-io/n8n
Pull request #15633: fix(core): Use destination node to select the correct pinned trigger to start from
Author: login: elsmr
Labels: name: core
description: Enhancement outside /nodes-base and /editor-ui
name: n8n team
description: Authored by the n8n team
name: Released
Created: 2025-05-23T10:29:01Z | Merged: 2025-05-23T14:29:53Z

## Summary

If there is a destination node, find the pinned activator that is a parent of the destination node

<img width="674" alt="image" src="https://github.com/user-attachments/assets/ac723479-33a5-4bd3-a65c-b46460f0fa70" />

## Related Linear tickets, Github issues, and Community forum posts

https://linear.app/n8n/issue/PAY-2347/manual-execution-waits-for-webhook-even-though-data-is-pinned

## Review / Merge checklist

- [ ] PR title and summary are descriptive. ([conventions](../blob/master/.github/pull_request_title_conventions.md)) <!--
   **Remember, the title automatically goes into the changelog.
   Use `(no-changelog)` otherwise.**
-->
- [ ] [Docs updated](https://github.com/n8n-io/n8n-docs) or follow-up ticket created.
- [ ] Tests included. <!--
   A bug is not considered fixed, unless a test is added to prevent it from happening again.
   A feature is not complete without tests.
-->
- [ ] PR Labeled with `release/backport` (if the PR is an urgent fix that needs to be backported)



Diff:
diff --git a/packages/cli/src/workflows/__tests__/workflow-execution.service.test.ts b/packages/cli/src/workflows/__tests__/workflow-execution.service.test.ts
index fb4b28fabf5d6..2068522cd1bbc 100644
--- a/packages/cli/src/workflows/__tests__/workflow-execution.service.test.ts
+++ b/packages/cli/src/workflows/__tests__/workflow-execution.service.test.ts
@@ -1,6 +1,13 @@
 import type { User } from '@n8n/db';
 import { mock } from 'jest-mock-extended';
-import type { INode, IWorkflowBase, INodeType, IWorkflowExecuteAdditionalData } from 'n8n-workflow';
+import {
+	NodeConnectionTypes,
+	type IConnections,
+	type INode,
+	type INodeType,
+	type IWorkflowBase,
+	type IWorkflowExecuteAdditionalData,
+} from 'n8n-workflow';
 
 import type { NodeTypes } from '@/node-types';
 import * as WorkflowExecuteAdditionalData from '@/workflow-execute-additional-data';
@@ -52,6 +59,15 @@ const hackerNewsNode: INode = {
 	position: [0, 0],
 };
 
+const secondHackerNewsNode: INode = {
+	name: 'Hacker News 2',
+	type: 'n8n-nodes-base.hackerNews',
+	id: '55d63bca-bb6c-4568-948f-8ed9aacb1fe3',
+	parameters: {},
+	typeVersion: 1,
+	position: [0, 0],
+};
+
 describe('WorkflowExecutionService', () => {
 	const nodeTypes = mock<NodeTypes>();
 	const workflowRunner = mock<WorkflowRunner>();
@@ -417,6 +433,23 @@ describe('WorkflowExecutionService', () => {
 			expect(node).toEqual(webhookNode);
 		});
 
+		it('should favor webhook node connected to the destination node', () => {
+			workflow.nodes.push(webhookNode, secondWebhookNode, hackerNewsNode, secondHackerNewsNode);
+			workflow.connections = {
+				...createMainConnection(webhookNode.name, hackerNewsNode.name),
+				...createMainConnection(secondWebhookNode.name, secondHackerNewsNode.name),
+			};
+
+			const node = workflowExecutionService.selectPinnedActivatorStarter(
+				workflow,
+				[],
+				{ ...pinData, [secondWebhookNode.name]: [{ json: { key: 'value' } }] },
+				secondHackerNewsNode.name,
+			);
+
+			expect(node).toEqual(secondWebhookNode);
+		});
+
 		describe('offloading manual executions to workers', () => {
 			test('when receiving no `runData`, should set `runData` to undefined in `executionData`', async () => {
 				const originalEnv = process.env;
@@ -458,3 +491,19 @@ describe('WorkflowExecutionService', () => {
 		});
 	});
 });
+
+function createMainConnection(targetNode: string, sourceNode: string): IConnections {
+	return {
+		[sourceNode]: {
+			[NodeConnectionTypes.Main]: [
+				[
+					{
+						node: targetNode,
+						type: 'main',
+						index: 0,
+					},
+				],
+			],
+		},
+	};
+}
diff --git a/packages/cli/src/workflows/workflow-execution.service.ts b/packages/cli/src/workflows/workflow-execution.service.ts
index 480db86b51fc4..b6b486149c78b 100644
--- a/packages/cli/src/workflows/workflow-execution.service.ts
+++ b/packages/cli/src/workflows/workflow-execution.service.ts
@@ -117,6 +117,7 @@ export class WorkflowExecutionService {
 			workflowData,
 			startNodes?.map((nodeData) => nodeData.name),
 			pinData,
+			destinationNode,
 		);
 
 		// TODO: Reverse the order of events, first find out if the execution is
@@ -378,7 +379,12 @@ export class WorkflowExecutionService {
 	 * prioritizing `n8n-nodes-base.webhook` over other activators. If the executed node
 	 * has no upstream nodes and is itself is a pinned activator, select it.
 	 */
-	selectPinnedActivatorStarter(workflow: IWorkflowBase, startNodes?: string[], pinData?: IPinData) {
+	selectPinnedActivatorStarter(
+		workflow: IWorkflowBase,
+		startNodes?: string[],
+		pinData?: IPinData,
+		destinationNode?: string,
+	) {
 		if (!pinData || !startNodes) return null;
 
 		const allPinnedActivators = this.findAllPinnedActivators(workflow, pinData);
@@ -389,7 +395,27 @@ export class WorkflowExecutionService {
 
 		// full manual execution
 
-		if (startNodes?.length === 0) return firstPinnedActivator ?? null;
+		if (startNodes?.length === 0) {
+			// If there is a destination node, find the pinned activator that is a parent of the destination node
+			if (destinationNode) {
+				const destinationParents = new Set(
+					new Workflow({
+						nodes: workflow.nodes,
+						connections: workflow.connections,
+						active: workflow.active,
+						nodeTypes: this.nodeTypes,
+					}).getParentNodes(destinationNode),
+				);
+
+				const activator = allPinnedActivators.find((a) => destinationParents.has(a.name));
+
+				if (activator) {
+					return activator;
+				}
+			}
+
+			return firstPinnedActivator ?? null;
+		}
 
 		// partial manual execution
 


Reviews:
user: login: cubic-dev-ai[bot]
body: cubic found 1 issue across 2 files. Review it in [cubic.dev](https://cubic.dev/pr/n8n-io/n8n/pull/15633)

<sub>React with 👍 or 👎 to teach cubic. Tag `@cubic-dev-ai` to give specific feedback.</sub>
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T10:33:00Z
user: login: despairblue
body: nice job!
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T11:49:38Z
user: login: despairblue
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T11:49:48Z

Review comments:
diff_hunk: @@ -417,6 +433,23 @@ describe('WorkflowExecutionService', () => {
 			expect(node).toEqual(webhookNode);
 		});
 
+		it('should favor first webhook node over second webhook node', () => {
path: packages/cli/src/workflows/__tests__/workflow-execution.service.test.ts
user: login: cubic-dev-ai[bot]
body: <!-- metadata:{"confidence":10,"steps":[{"text":"I'll review the changed lines in the PR to identify any potential issues. Let me start by understanding the context and the changes made.","toolCalls":[{"args":{"pattern":"packages/cli/src/workflows/workflow-execution.service.ts"},"toolName":"listFiles"}]},{"text":"Let me examine the implementation file to understand the context better:","toolCalls":[{"args":{"command":"grep -A 30 \"selectPinnedActivatorStarter\" packages/cli/src/workflows/workflow-execution.service.ts"},"toolName":"executeCommand"}]},{"text":"Now I'll look at the implementation of the `findAllPinnedActivators` method to understand how it works:","toolCalls":[{"args":{"command":"grep -A 20 \"findAllPinnedActivators\" packages/cli/src/workflows/workflow-execution.service.ts"},"toolName":"executeCommand"}]},{"text":"Now I'll look at the test file to understand the changes better:","toolCalls":[{"args":{"command":"grep -A 20 \"should favor first webhook node over second webhook node\" packages/cli/src/workflows/__tests__/workflow-execution.service.test.ts"},"toolName":"executeCommand"}]},{"text":"Based on my analysis of the code changes and the context, I'll now review the changes for potential issues.\n\nThe changes in this PR are focused on improving the selection of the correct pinned trigger to start from when there's a destination node specified. The main change is adding a new test case that verifies the behavior of selecting the appropriate webhook node based on the workflow connections and destination node.\n\nLet me check for any issues in the added code:","toolCalls":[{"args":{"command":"grep -n \"createMainConnection\" packages/cli/src/workflows/__tests__/workflow-execution.service.test.ts"},"toolName":"executeCommand"}]},{"text":"Now I'll analyze the changes for potential issues:\n\n1. The PR adds imports for `NodeConnectionTypes` and `IConnections` types from 'n8n-workflow'.\n2. It adds a new `secondHackerNewsNode` constant for testing.\n3. It adds a new test case to verify that when a destination node is specified, the system should select the pinned activator that is a parent of the destination node.\n4. It adds a utility function `createMainConnection` to help create connection objects for testing.\n\nLet me check for any potential issues in these changes:","toolCalls":[{"args":{"command":"grep -n \"should favor first webhook node over second webhook node\" packages/cli/src/workflows/__tests__/workflow-execution.service.test.ts"},"toolName":"executeCommand"}]}]} -->
Duplicate test name. This test has the same name as the previous test but tests different functionality.
created_at: 2025-05-23T10:33:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -417,6 +433,23 @@ describe('WorkflowExecutionService', () => {
 			expect(node).toEqual(webhookNode);
 		});
 
+		it('should favor first webhook node over second webhook node', () => {
path: packages/cli/src/workflows/__tests__/workflow-execution.service.test.ts
user: login: despairblue
body: fixed
created_at: 2025-05-23T11:49:47Z
author_association: CONTRIBUTOR

PR comments:
user: login: codecov[bot]
created_at: 2025-05-23T10:35:15Z
body: ## [Codecov](https://app.codecov.io/gh/n8n-io/n8n/pull/15633?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=n8n-io) Report
Attention: Patch coverage is `62.50000%` with `3 lines` in your changes missing coverage. Please review.
| [Files with missing lines](https://app.codecov.io/gh/n8n-io/n8n/pull/15633?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=n8n-io) | Patch % | Lines |
|---|---|---|
| [...es/cli/src/workflows/workflow-execution.service.ts](https://app.codecov.io/gh/n8n-io/n8n/pull/15633?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=n8n-io#diff-cGFja2FnZXMvY2xpL3NyYy93b3JrZmxvd3Mvd29ya2Zsb3ctZXhlY3V0aW9uLnNlcnZpY2UudHM=) | 62.50% | [2 Missing and 1 partial :warning: ](https://app.codecov.io/gh/n8n-io/n8n/pull/15633?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=n8n-io) |

:loudspeaker: Thoughts on this report? [Let us know!](https://github.com/codecov/feedback/issues/255)
author_association: NONE
user: login: shortstacked
created_at: 2025-05-23T11:51:50Z
body: ## Workflow Test Results 📊 🔴 **1 Failed,** ⚠️ 4 Warnings, 👍 78 Successful out of 83 total workflows.
*Detail:* Workflows failing: *84*: Unable to introspect the access token on node Matrix7  [View full workflow run](https://github.com/n8n-io/n8n/actions/runs/15209577322)

*Tested Ref:* `4ebc6be1e43139abb27e395a756567e11bd001d0` by @despairblue
### ❌ Failed Tests (1)
| Workflow ID | Workflow Name | Reason |
|-------------|---------------|--------|
| 84 | Matrix:Room:create invite kick leave:RoomMember:ge... | Unable to introspect the access token on node Matrix7 |
### ⚠️ Warnings (4)
| Workflow ID | Workflow Name | Reason |
|-------------|---------------|--------|
| 237 | BasicLLMChain:AzureChat | Workflow contains new data that previously did not exist. |
| 35 | Slack:User:getPresence info:UserProfile:get update... | Workflow contains new data that previously did not exist. |
| 257 | Agent:auto-fix:anthropic | Workflow contains new data that previously did not exist. |
| 53 | ConvertKit:CustomField:create getAll update delete... | Workflow contains new data that previously did not exist. |
author_association: COLLABORATOR
user: login: github-actions[bot]
created_at: 2025-05-23T11:59:01Z
body: :warning: Some Cypress E2E specs are failing, please fix them before merging
author_association: CONTRIBUTOR
user: login: janober
created_at: 2025-05-26T13:32:48Z
body: Got released with [`n8n@1.95.0`](https://github.com/n8n-io/n8n/releases/tag/n8n%401.95.0)
author_association: MEMBER