n8n-io/n8n · error
Failed to load existing workflow
Error message
Failed to load existing workflow ${workflowId} to preserve node positions: ${message} What it means
preserveExistingNodePositions tried to load the saved workflow by id so node positions could be reconciled by name, but workflowService.getAsWorkflowJSON failed. The load error is wrapped into an explicit message because silently skipping would risk scattering the user's hand-arranged canvas.
Solutions
- Check the workflow id is valid and the workflow still exists / is accessible
- Resolve the underlying service error (connection or permissions) and rebuild
Defensive patterns
Strategy: try-catch
When it happens
Trigger: Thrown at packages/@n8n/instance-ai/src/tools/workflows/preserve-node-positions.ts:192 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/d9acf79b312fbdc7.
Report an issue: GitHub.
Appendix: source
Thrown at packages/@n8n/instance-ai/src/tools/workflows/preserve-node-positions.ts:192
* engine put it — scattering a canvas the user had arranged by hand. Reconciling by
* name here keeps the user's layout authoritative, mirroring ensureWebhookIds.
*
* Nodes the build added are translated into the saved canvas's frame, keeping the
* layout engine's relative arrangement, then nudged clear of anything they land on.
*/
export async function preserveExistingNodePositions(
json: WorkflowJSON,
workflowId: string | undefined,
ctx: InstanceAiContext,
): Promise<void> {
if (!workflowId) return;
let existing: WorkflowJSON;
try {
existing = await ctx.workflowService.getAsWorkflowJSON(workflowId);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new Error(
`Failed to load existing workflow ${workflowId} to preserve node positions: ${message}`,
{ cause: error },
);
}
const savedPositionsByName = new Map<string, Position>();
for (const node of existing.nodes ?? []) {
if (node.name && Array.isArray(node.position)) {
savedPositionsByName.set(node.name, [node.position[0], node.position[1]]);
}
}
if (savedPositionsByName.size === 0) return;
const nodes = json.nodes ?? [];
const survivors: Survivor[] = [];
const added: NodeJSON[] = [];
for (const node of nodes) {
const saved = node.name ? savedPositionsByName.get(node.name) : undefined;View on GitHub (pinned to 5ac6606e81)