{"record":{"id":"8729106c43a946a1","repo":"coleam00/Archon","slug":"workflow-parent-resume-nothing-to-resume","errorCode":"workflow.parent_resume_nothing_to_resume","errorMessage":"the parent had no resumable state","messagePattern":"the parent had no resumable state","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/workflows/src/executor.ts","lineNumber":1717,"sourceCode":"    // hydrate's last step; a lost CAS throws WorkflowNotResumableError instead) —\n    // the parent stays 'paused' and manually resumable, so log and stand down.\n    if (err instanceof Error && err.name === 'WorkflowNotResumableError') {\n      // Benign race: a concurrent (manual or duplicate) resume won the CAS and\n      // now owns the parent. Not an error — no user-facing message (it IS resuming).\n      getLog().info(\n        { parentRunId, childRunId: childRun.id },\n        'workflow.parent_auto_resume_lost_race'\n      );\n    } else {\n      getLog().error({ err: err as Error, parentRunId }, 'workflow.parent_resume_hydrate_failed');\n      await notifyStuck('preparing the parent for resume failed');\n    }\n    return;\n  }\n  if (!hydrated) {\n    // A parent paused on a child_workflow gate is always resumable (see the\n    // child_workflow branch in hydrateResumableRun), so null here is unexpected.\n    getLog().warn({ parentRunId }, 'workflow.parent_resume_nothing_to_resume');\n    await notifyStuck('the parent had no resumable state');\n    return;\n  }\n\n  getLog().info(\n    { parentRunId, childRunId: childRun.id, childStatus: childRun.status },\n    'workflow.parent_auto_resume_started'\n  );\n  try {\n    await executeWorkflow(\n      deps,\n      platform,\n      conversationId,\n      parentCwd,\n      parentWorkflow,\n      parent.user_message ?? '',\n      conversationDbId,\n      {","sourceCodeStart":1699,"sourceCodeEnd":1735,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/workflows/src/executor.ts#L1699-L1735","documentation":"When a child workflow run changes state and the executor tries to resume its parent, it hydrates the parent's resumable state. A parent paused on a child_workflow gate is always resumable by invariant, so a null hydration result means the parent's pause record is missing or inconsistent. The executor logs a warning, notifies the operator the run is stuck, and abandons the resume rather than proceeding with undefined state.","triggerScenarios":"resumeParent flow (executor.ts:1717): a child run's completion/pause triggers parent resume, and hydrateResumableRun returns hydrated === null for the parent — e.g. the parent's child_workflow gate pause record was deleted, pruned, overwritten by an out-of-band resume/cancel, or never persisted due to an interrupted write.","commonSituations":"Manual DB cleanup or retention pruning that removed the parent's pause metadata; resuming a child whose parent was already cancelled/failed with its pause state cleared; a crash between pausing the parent and writing its resumable record; store state shape changed by an upgrade.","solutions":["Inspect the parent run's persisted pause/resumable state; if the child_workflow pause record was lost, restore it from backup or recreate the pause state.","Resume the parent directly with `archon workflow resume <parentRunId>` so it re-hydrates its own gate state instead of relying on the child-triggered path.","If the parent is genuinely inconsistent, fail or cancel it explicitly and start a fresh run of the workflow.","Check for pruning jobs or interrupted writes that could have removed the record; report persistent cases with run IDs since null here should be impossible."],"exampleFix":"# before: resuming the child in isolation (parent has no state)\n$ archon workflow resume <childRunId>\n# after: resume the parent whose gate state is intact (or restart it)\n$ archon workflow resume <parentRunId>","handlingStrategy":"validation","validationCode":"// Confirm the parent actually has resumable state before relying on a child-triggered resume:\nconst status = await store.getWorkflowRunStatus(parentRunId);\nif (status !== 'paused' && status !== 'waiting') {\n  throw new Error(`Parent ${parentRunId} has no resumable pause state (${status})`);\n}","typeGuard":"function isResumableParent(status: string | null): status is 'paused' | 'waiting' {\n  return status === 'paused' || status === 'waiting';\n}","tryCatchPattern":null,"preventionTips":["Never delete or prune a parent run's pause records while its child runs are still active.","Resume parents via the CLI rather than mutating run state directly in the store.","Treat a 'nothing to resume' warning as a data-integrity bug: capture run IDs and investigate, don't just restart blindly.","Keep the parent's lifecycle consistent (cancel/fail it properly) before resuming orphaned children."],"tags":["workflow","resume","state","child-workflow"],"backgroundTag":"missing-resume-state","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}