{"record":{"id":"ec1e69bb3080749e","repo":"coleam00/Archon","slug":"failed-to-wait-for-workflow-run-err-message","errorCode":null,"errorMessage":"Failed to wait for workflow run: ${err.message}","messagePattern":"Failed to wait for workflow run: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/workflow.ts","lineNumber":3615,"sourceCode":"  let resolvedId: string;\n  try {\n    resolvedId = await resolveRunIdArg(runId, cwd);\n    result = await waitForRunAttention(resolvedId, {\n      // No timeout by default: a wait that ends on its own clock would answer a\n      // question only the run can answer.\n      ...(timeoutSeconds === undefined ? {} : { deadlineMs: timeoutSeconds * 1000 }),\n      onAttached: observedStatus => announceWaitAttached(resolvedId, observedStatus, json),\n    });\n  } catch (error) {\n    const err = error as Error;\n    getLog().error({ err, runId }, 'cli.workflow_wait_failed');\n    // In --json mode never throw — emit one parseable {ok:false} line (same contract\n    // as `get` and the write commands) so a parsing agent always gets JSON.\n    if (json) {\n      await writeJsonLine({ ok: false, runId, action: 'wait', error: err.message });\n      return 1;\n    }\n    throw new Error(`Failed to wait for workflow run: ${err.message}`);\n  }\n\n  if (result.kind === 'not_found') {\n    if (json) {\n      await writeJsonLine({ ok: false, runId, action: 'wait', error: 'not_found' });\n    } else {\n      console.log(formatWaitOutcome(resolvedId, result));\n    }\n    return 1;\n  }\n\n  if (json) {\n    await writeJsonLine({\n      ok: true,\n      action: 'wait',\n      runId: resolvedId,\n      result: result.kind,\n      ...(result.kind === 'attention' ? { attention: result.attention } : {}),","sourceCodeStart":3597,"sourceCodeEnd":3633,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/cli/src/commands/workflow.ts#L3597-L3633","documentation":"`archon workflow wait <runId>` polls until a run reaches a terminal state; if waiting throws, the CLI logs and either emits `{ok:false, runId, action:'wait', error}` JSON (in `--json` mode it never throws, matching the get/write contract) or re-throws 'Failed to wait for workflow run: <message>'.","triggerScenarios":"Waiting on a run when the wait API throws: database connection lost mid-poll, storage adapter error, or a corrupt run record preventing status resolution (distinct from the handled `not_found` result kind).","commonSituations":"Long waits spanning a network DB outage; SQLite lock contention while the run writes; run record corrupted by a crashed writer; repeated transient DB errors until the wait gives up.","solutions":["Retry the wait command — it is idempotent and will re-poll.","Verify DB connectivity if waits fail repeatedly (network, DSN, locks).","Use `archon workflow get <runId> --json` to check whether the run exists and its state.","In scripts, use `--json` mode and handle the `{ok:false, action:'wait'}` line instead of parsing thrown errors."],"exampleFix":"// before\nconst code = await waitCommand(runId); // throws on failure\n// after\nconst code = await waitCommand(runId, { json: true });\n// parse emitted line: { ok: false, runId, action: 'wait', error } and handle explicitly","handlingStrategy":"try-catch","validationCode":"// confirm the run exists before waiting\nconst status = await getRunStatus(runId);\nif (status.kind === 'not_found') throw new Error(`Run ${runId} not found`);","typeGuard":"function isNotFound(r: { kind: string }): r is { kind: 'not_found' } {\n  return r.kind === 'not_found';\n}","tryCatchPattern":"try {\n  const result = await waitForRun(runId);\n} catch (err) {\n  const e = err as Error;\n  if (json) {\n    await writeJsonLine({ ok: false, runId, action: 'wait', error: e.message });\n    return 1;\n  }\n  throw new Error(`Failed to wait for workflow run: ${e.message}`);\n}","preventionTips":["Verify the run ID exists (`archon workflow get`) before waiting.","Keep database connectivity stable across long waits; prefer local SQLite for long polls.","In automation, always use `--json` and branch on the `{ok:false}` line.","Treat repeated wait failures as a storage-layer problem, not a workflow failure."],"tags":["cli","wait","polling"],"backgroundTag":"database-read-failed","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}