{"record":{"id":"ee35a3a4eaaeaf9c","repo":"coleam00/Archon","slug":"workflow-run-resolvedid-has-no-working-path-r-ee35a3","errorCode":null,"errorMessage":"Workflow run '${resolvedId}' has no working path recorded.\nCannot determine where to resume.","messagePattern":"Workflow run '(.+?)' has no working path recorded\\.\nCannot determine where to resume\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/workflow.ts","lineNumber":4513,"sourceCode":"  // --detach: hand the approve AND its inline auto-resume to a detached child\n  // (same argv minus --detach/--json). Handled BEFORE any state change — the\n  // parent only validates read-only, so the approval is recorded exactly once,\n  // in the child. Composes with --json (structured ack; nothing executes here).\n  if (detach) {\n    const resolvedId = await resolveRunIdArg(runId, cwd);\n    await runDetachedControlCommand(resolvedId, 'approve', json, cwd, async () => {\n      const run = await workflowDb.getWorkflowRun(resolvedId);\n      if (!run) {\n        throw new Error(`Workflow run not found: ${resolvedId}`);\n      }\n      // The SAME gate approveWorkflow enforces — not a copy of one branch of it.\n      // A partial copy acks { ok: true } and lets the child die unseen.\n      assertApprovable(run);\n      // The child always auto-resumes after approving, and the inline path below\n      // refuses a run with no recorded working path. Same check here (message\n      // copied verbatim) so the refusal is synchronous instead of buried in a log.\n      if (!run.working_path) {\n        throw new Error(\n          `Workflow run '${resolvedId}' has no working path recorded.\\n` +\n            'Cannot determine where to resume.'\n        );\n      }\n      return run;\n    });\n    return;\n  }\n\n  // JSON mode records the approval and returns a structured ack WITHOUT the\n  // inline auto-resume (resuming executes the workflow and streams output to\n  // stdout, which would corrupt the JSON contract). The run becomes resumable\n  // — drive it to completion with a backgrounded `resume`/`run --resume`.\n  if (json) {\n    try {\n      const resolvedId = await resolveRunIdArg(runId, cwd);\n      const result = await approveWorkflow(resolvedId, comment);\n      await writeJsonLine({","sourceCodeStart":4495,"sourceCodeEnd":4531,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/cli/src/commands/workflow.ts#L4495-L4531","documentation":"The `archon workflow approve --json --detach` path resolves the run, asserts it is approvable, then refuses to proceed if the run has no recorded working_path. The working path is where the child process executes; without it the CLI cannot know where to resume the run after approval, so it fails synchronously instead of acking and letting the child die unseen.","triggerScenarios":"Calling `workflow approve <id> --json --detach` (or any detach path that runs this pre-check) on a run whose `working_path` column is null/empty — e.g. a run created before working-path tracking, a manually seeded DB row, or a run whose workspace directory record was lost.","commonSituations":"Operators upgrading an older database whose rows predate working_path recording; runs created through direct DB manipulation or import tooling; corrupted/partial run records after a crash during run creation.","solutions":["Verify the run actually has a workspace: check the run record (e.g. via `workflow list`/DB query) for a non-empty working_path.","Re-create or re-launch the run so the engine records a fresh working path instead of resuming the orphaned record.","If the workspace directory still exists on disk, backfill working_path in the database to that directory, then retry the approve.","If the run is dead/abandoned, reject or cancel it rather than approving."],"exampleFix":"// before\nawait approveWorkflow(resolvedId, comment); // may hit a run with working_path = null\n// after\nconst run = await workflowDb.getWorkflowRun(resolvedId);\nif (!run) throw new Error(`Workflow run not found: ${resolvedId}`);\nif (!run.working_path) throw new Error(`Workflow run '${resolvedId}' has no working path recorded.`);\nawait approveWorkflow(resolvedId, comment);","handlingStrategy":"validation","validationCode":"import { workflowDb } from '../db.js';\nconst run = await workflowDb.getWorkflowRun(resolvedId);\nif (!run) throw new Error(`Workflow run not found: ${resolvedId}`);\nif (!run.working_path) throw new Error(`Run ${resolvedId} has no working path; fix or recreate before approving.`);","typeGuard":"function hasWorkingPath(run: { working_path?: string | null }): run is { working_path: string } {\n  return typeof run.working_path === 'string' && run.working_path.length > 0;\n}","tryCatchPattern":"try {\n  await approveDetached(resolvedId, comment);\n} catch (e) {\n  if ((e as Error).message.includes('no working path recorded')) {\n    // inspect/backfill the run record before retrying\n  }\n  throw e;\n}","preventionTips":["Check the run's working_path before scripting approve/reject/respond calls","Avoid inserting or importing run rows directly into the database","Keep the engine upgraded so working-path recording bugs are patched","Treat runs without a workspace as terminal and recreate them instead of resuming"],"tags":["cli","workflow","state"],"backgroundTag":"missing-working-path","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}