fix(core): Replace misleading "No path back to node" error with helpful execution message (#17759)

This commit is contained in:
Csaba Tuncsik
2025-07-29 17:22:11 +02:00
committed by GitHub
parent d16960bad3
commit 164800f6a4
4 changed files with 710 additions and 9 deletions

View File

@@ -286,8 +286,10 @@ describe('WorkflowDataProxy', () => {
} catch (error) {
expect(error).toBeInstanceOf(ExpressionError);
const exprError = error as ExpressionError;
expect(exprError.message).toEqual('Error finding the referenced node');
expect(exprError.context.type).toEqual('paired_item_no_connection');
expect(exprError.message).toEqual('No execution data available');
expect(exprError.context.messageTemplate).toEqual(
'Execute node "Impossible if" for preview',
);
}
});
@@ -826,4 +828,207 @@ describe('WorkflowDataProxy', () => {
expect(proxy.$('Set main variable').item.json.main_variable).toEqual(2);
});
});
describe('Improved error messages for missing execution data', () => {
test('should show helpful error message when accessing node without execution data', () => {
// Create a simple workflow with two connected nodes
const workflow: IWorkflowBase = {
id: '1',
name: 'test-workflow',
nodes: [
{
id: '1',
name: 'Telegram Trigger',
type: 'n8n-nodes-base.telegramTrigger',
typeVersion: 1.2,
position: [0, 0],
parameters: {},
},
{
id: '2',
name: 'Send a text message',
type: 'n8n-nodes-base.telegram',
typeVersion: 1.2,
position: [576, 0],
parameters: {
chatId: "={{ $('Telegram Trigger').item.json.message.chat.id }}",
text: 'Test message',
},
},
],
connections: {
'Telegram Trigger': {
main: [[{ node: 'Send a text message', type: NodeConnectionTypes.Main, index: 0 }]],
},
},
active: false,
isArchived: false,
createdAt: new Date(),
updatedAt: new Date(),
};
// Create run data without execution data for Telegram Trigger
const run = {
data: {
resultData: {
runData: {}, // Empty - no nodes have executed
},
},
mode: 'manual' as const,
startedAt: new Date(),
status: 'success' as const,
};
const proxy = getProxyFromFixture(workflow, run, 'Send a text message');
// Should throw helpful error when trying to access Telegram Trigger data
let error: ExpressionError | undefined;
try {
proxy.$('Telegram Trigger').item;
} catch (e) {
error = e as ExpressionError;
}
expect(error).toBeDefined();
expect(error).toBeInstanceOf(ExpressionError);
expect(error!.message).toBe('No execution data available');
expect(error!.context.messageTemplate).toBe('Execute node "Telegram Trigger" for preview');
expect(error!.context.nodeCause).toBe('Telegram Trigger');
});
test('should show helpful error message for different node names', () => {
const workflow: IWorkflowBase = {
id: '1',
name: 'test-workflow',
nodes: [
{
id: '1',
name: 'HTTP Request',
type: 'n8n-nodes-base.httpRequest',
typeVersion: 1,
position: [0, 0],
parameters: {},
},
{
id: '2',
name: 'Process Data',
type: 'n8n-nodes-base.code',
typeVersion: 2,
position: [300, 0],
parameters: {
jsCode: "return $('HTTP Request').all();",
},
},
],
connections: {
'HTTP Request': {
main: [[{ node: 'Process Data', type: NodeConnectionTypes.Main, index: 0 }]],
},
},
active: false,
isArchived: false,
createdAt: new Date(),
updatedAt: new Date(),
};
const run = {
data: {
resultData: {
runData: {}, // Empty - no nodes have executed
},
},
mode: 'manual' as const,
startedAt: new Date(),
status: 'success' as const,
};
const proxy = getProxyFromFixture(workflow, run, 'Process Data');
let error: ExpressionError | undefined;
try {
proxy.$('HTTP Request').item;
} catch (e) {
error = e as ExpressionError;
}
expect(error).toBeDefined();
expect(error!.context.messageTemplate).toBe('Execute node "HTTP Request" for preview');
expect(error!.context.nodeCause).toBe('HTTP Request');
});
test('should use improved error for first(), last(), and all() methods', () => {
const workflow: IWorkflowBase = {
id: '1',
name: 'test-workflow',
nodes: [
{
id: '1',
name: 'Start Node',
type: 'n8n-nodes-base.manualTrigger',
typeVersion: 1,
position: [0, 0],
parameters: {},
},
{
id: '2',
name: 'End Node',
type: 'n8n-nodes-base.noOp',
typeVersion: 1,
position: [300, 0],
parameters: {},
},
],
connections: {
'Start Node': {
main: [[{ node: 'End Node', type: NodeConnectionTypes.Main, index: 0 }]],
},
},
active: false,
isArchived: false,
createdAt: new Date(),
updatedAt: new Date(),
};
const run = {
data: {
resultData: {
runData: {}, // Empty - no nodes have executed
},
},
mode: 'manual' as const,
startedAt: new Date(),
status: 'success' as const,
};
const proxy = getProxyFromFixture(workflow, run, 'End Node');
// Test first() method
let error: ExpressionError | undefined;
try {
proxy.$('Start Node').first();
} catch (e) {
error = e as ExpressionError;
}
expect(error).toBeDefined();
expect(error!.context.messageTemplate).toBe('Execute node "Start Node" for preview');
// Test last() method
try {
proxy.$('Start Node').last();
} catch (e) {
error = e as ExpressionError;
}
expect(error).toBeDefined();
expect(error!.context.messageTemplate).toBe('Execute node "Start Node" for preview');
// Test all() method
try {
proxy.$('Start Node').all();
} catch (e) {
error = e as ExpressionError;
}
expect(error).toBeDefined();
expect(error!.context.messageTemplate).toBe('Execute node "Start Node" for preview');
});
});
});