{"record":{"id":"f7826d77527e77c9","repo":"coleam00/Archon","slug":"failed-to-find-resumable-run-err-message","errorCode":null,"errorMessage":"Failed to find resumable run: ${err.message}","messagePattern":"Failed to find resumable run: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/db/workflows.ts","lineNumber":836,"sourceCode":"  try {\n    const result = await pool.query<WorkflowRun>(\n      `SELECT * FROM remote_agent_workflow_runs\n       WHERE workflow_name = $1\n         AND working_path = $2\n         AND ${resumableStatusClause(dialect, 3)}\n       ORDER BY started_at DESC\n       LIMIT 1`,\n      [workflowName, workingPath, ORPHAN_RESUME_STALE_DAYS]\n    );\n    const row = result.rows[0];\n    return row ? normalizeWorkflowRun(row) : null;\n  } catch (error) {\n    const err = error as Error;\n    getLog().error(\n      { err, errorType: err.constructor.name, workflowName, workingPath },\n      'db.workflow_run_find_resumable_failed'\n    );\n    throw new Error(`Failed to find resumable run: ${err.message}`);\n  }\n}\n\n/**\n * Find a resumable (failed/paused) run for a workflow scoped to (parent conversation, codebase).\n * Used by the orchestrator (all platforms) to detect approved runs that need foreground resume\n * on the prior run's worktree. Codebase scope prevents cross-project resume on persistent\n * chat conversation IDs (Telegram chat_id, Slack thread, etc.).\n *\n * Ordering is status-first, then recency WITHIN a status — not bare recency. The two statuses\n * are not interchangeable candidates for the caller: a `paused` run is an open gate that is\n * legitimately waiting and gets hydrated and resumed, while a `failed` one is deliberately gated\n * behind an explicit user prompt first (#1549). Ordering purely by `started_at` therefore lets a\n * newer failure shadow an older open gate, and approving that gate resumes nothing.\n *\n * Contrast with getActiveWorkflowRunByPath below, which sorts the opposite way (older-wins) —\n * it answers \"who took the path lock first\", a different question.\n */","sourceCodeStart":818,"sourceCodeEnd":854,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/core/src/db/workflows.ts#L818-L854","documentation":"findResumableRun locates a failed/paused run for a given workflow name and working path so it can be resumed instead of duplicated. DB failures are logged with rich context (err, errorType, workflowName, workingPath) under db.workflow_run_find_resumable_failed and rethrown wrapped in this message. No matching run returns null and does not throw.","triggerScenarios":"Calling findResumableRun({ workflowName, workingPath }) when the database is unreachable, the workflow_runs table/columns are missing from an un-migrated DB, or the query times out under pool contention.","commonSituations":"Fresh install against an existing DB without running upgrades; SQLite file locked by another process; Postgres restarted between workflow steps; typos in DSN config in a secondary environment.","solutions":["Check the db.workflow_run_find_resumable_failed log's err and errorType fields for the driver cause.","Ensure migrations created workflow_runs with the columns the resumable query filters on (status, working_path).","Verify DB connectivity / SQLite file locking, then retry the read-only lookup."],"exampleFix":"// before\nconst run = await findResumableRun({ workflowName, workingPath });\n// after\nlet run: WorkflowRun | null = null;\ntry {\n  run = await findResumableRun({ workflowName, workingPath });\n} catch (err) {\n  getLog().warn({ err }, 'resume_lookup_failed_starting_fresh');\n}","handlingStrategy":"try-catch","validationCode":"const ping = await pool.query('SELECT 1'); // DB reachable before resume detection","typeGuard":"function isFindResumableError(err: unknown): err is Error {\n  return err instanceof Error && err.message.startsWith('Failed to find resumable run:');\n}","tryCatchPattern":"try {\n  const run = await findResumableRun({ workflowName, workingPath });\n} catch (err) {\n  // null means no resumable run (normal); throwing here means DB failure.\n  getLog().error({ err }, 'resumable_probe_failed');\n  run = null; // or rethrow if starting a duplicate run is unacceptable\n}","preventionTips":["Remember null (no match) is success — never map null to the error path.","Run DB upgrades on every environment a workflow touches (including dev SQLite files).","Check SQLite file locking if using the SQLite adapter.","Alert on db.workflow_run_find_resumable_failed events."],"tags":["database","workflow-resume"],"backgroundTag":"database-query-failed","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}