{"record":{"id":"c0898e424603a52b","repo":"n8n-io/n8n","slug":"checkpoint-task-task-id-must-depend-on-at-lea","errorCode":null,"errorMessage":"Checkpoint task \"${task.id}\" must depend on at least one build-workflow task","messagePattern":"Checkpoint task \"(.+?)\" must depend on at least one build-workflow task","errorType":"validation","errorClass":"PlanValidationError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/instance-ai/src/planned-tasks/planned-task-service.ts","lineNumber":45,"sourceCode":"\treturn new Set(tasks.map((task) => task.id)).size !== tasks.length;\n}\n\nfunction validateDependencies(tasks: PlannedTask[]): void {\n\tif (hasDuplicateIds(tasks)) {\n\t\tthrow new PlanValidationError('Plan contains duplicate task IDs');\n\t}\n\n\tconst knownIds = new Set(tasks.map((task) => task.id));\n\tconst byId = new Map(tasks.map((task) => [task.id, task]));\n\tfor (const task of tasks) {\n\t\tfor (const depId of task.deps) {\n\t\t\tif (!knownIds.has(depId)) {\n\t\t\t\tthrow new PlanValidationError(`Task \"${task.id}\" depends on unknown task \"${depId}\"`);\n\t\t\t}\n\t\t}\n\t\tif (task.kind === 'checkpoint') {\n\t\t\tif (task.deps.length === 0) {\n\t\t\t\tthrow new PlanValidationError(\n\t\t\t\t\t`Checkpoint task \"${task.id}\" must depend on at least one build-workflow task`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst dependsOnBuildWorkflow = task.deps.some(\n\t\t\t\t(depId) => byId.get(depId)?.kind === 'build-workflow',\n\t\t\t);\n\t\t\tif (!dependsOnBuildWorkflow) {\n\t\t\t\tthrow new PlanValidationError(\n\t\t\t\t\t`Checkpoint task \"${task.id}\" must depend on at least one build-workflow task`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst visiting = new Set<string>();\n\tconst visited = new Set<string>();\n\n\tconst visit = (taskId: string) => {","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/instance-ai/src/planned-tasks/planned-task-service.ts#L27-L63","documentation":"Thrown as a PlanValidationError by validateDependencies (planned-task-service.ts:44-48) when a task with kind === 'checkpoint' has an empty deps array. Checkpoints represent user-approval gates and must gate at least one build-workflow task; a checkpoint with no deps has nothing to gate. This is the first of two checkpoint-dep checks (the second, error 515, requires at least one dep to be build-workflow kind).","triggerScenarios":"A submitted plan includes { kind: 'checkpoint', deps: [] }. The empty-deps check runs before the kind check, so this fires even if non-build-workflow deps would otherwise be acceptable.","commonSituations":"LLM models a checkpoint as a standalone task; a programmatic builder creates a checkpoint template and forgets to wire deps; the plan was edited and deps were cleared.","solutions":["Add at least one dep to the checkpoint, pointing at the build-workflow task(s) it should gate.","Reconsider whether a checkpoint is needed at all — if there is nothing to gate, remove it.","Re-call the plan tool with the corrected checkpoint deps."],"exampleFix":"// before: { id: 'cp1', kind: 'checkpoint', deps: [] }\n// after:  { id: 'cp1', kind: 'checkpoint', deps: ['build-1'] }","handlingStrategy":"validation","validationCode":"for (const t of tasks) {\n  if (t.kind === 'checkpoint' && t.deps.length === 0) {\n    throw new Error(`Checkpoint \"${t.id}\" needs at least one dep`);\n  }\n}","typeGuard":"function checkpointsHaveDeps(tasks: { kind: string; deps: string[] }[]): boolean {\n  return tasks.every(t => t.kind !== 'checkpoint' || t.deps.length > 0);\n}","tryCatchPattern":"try { await coordinator.createPlan(threadId, tasks, meta); }\ncatch (e) {\n  if (e instanceof PlanValidationError) {\n    // surface to LLM for retry\n  }\n  throw e;\n}","preventionTips":["Always wire checkpoint deps to the build-workflow tasks they gate.","If nothing is gated, drop the checkpoint.","Validate checkpoint shape locally before submission."],"tags":["planned-tasks","validation","plan-graph","checkpoint","llm-retryable"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}