{"record":{"id":"d2c470caaafd3e6c","repo":"coleam00/Archon","slug":"failed-to-resume-workflow-run-err-message","errorCode":null,"errorMessage":"Failed to resume workflow run: ${err.message}","messagePattern":"Failed to resume workflow run: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/db/workflows.ts","lineNumber":991,"sourceCode":"        await insertWorkflowEvent(query, {\n          workflow_run_id: id,\n          event_type: 'workflow_resumed',\n          data: { error: clearedError },\n        });\n      }\n      if (rowCount > 0 && scheduled !== null && triggeredAt !== null) {\n        await insertWorkflowEvent(query, {\n          workflow_run_id: id,\n          event_type: 'quota_resume_triggered',\n          data: { attempt: scheduled.attempt, resume_at: scheduled.resumeAt },\n        });\n      }\n      return { rowCount };\n    });\n  } catch (error) {\n    const err = error as Error;\n    getLog().error({ err, workflowRunId: id }, 'db.workflow_run_resume_failed');\n    throw new Error(`Failed to resume workflow run: ${err.message}`);\n  }\n\n  if (updateResult.rowCount === 0) {\n    // CAS miss: the row is no longer resumable — deleted, terminal, or already\n    // activated by another caller. Refuse rather than double-claim the worktree.\n    // Probe the current status for an actionable error (informational only; the\n    // probe rethrows on its own failure).\n    let probeRows: readonly { status: string }[];\n    try {\n      const probe = await pool.query<{ status: string }>(\n        'SELECT status FROM remote_agent_workflow_runs WHERE id = $1',\n        [id]\n      );\n      probeRows = probe.rows;\n    } catch (error) {\n      const err = error as Error;\n      getLog().error({ err, workflowRunId: id }, 'db.workflow_run_resume_probe_failed');\n      throw new Error(`Failed to resume workflow run: ${err.message}`, { cause: err });","sourceCodeStart":973,"sourceCodeEnd":1009,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/core/src/db/workflows.ts#L973-L1009","documentation":"resumeWorkflowRun performs a compare-and-swap UPDATE that flips a run from failed/paused to an active state; any driver error inside that transaction is logged (db.workflow_run_resume_failed) and rethrown wrapped in this message. Note the same message is reused for the CAS-miss path after the try/catch (see [249] for the probe's own wrapper) — this instance specifically means the resume transaction itself hit a database error, not a status conflict.","triggerScenarios":"Calling resumeWorkflowRun(id, cursor) when the UPDATE/INSERTs inside the transaction fail: connection dropped mid-transaction, deadlock with another resume attempt, constraint violation on inserted events, or insufficient UPDATE privileges.","commonSituations":"Two operators (or the scheduler and a user) resuming the same run concurrently causing lock contention; DB failover mid-transaction; workflow_events insert blocked by schema drift.","solutions":["Read the db.workflow_run_resume_failed log for the underlying driver error.","Retry the resume after transient errors — the CAS design prevents double-claiming, so a retry is safe.","If the CAS-miss error follows, call again only after checking the run's current status via getWorkflowRunStatus.","Verify UPDATE permissions on workflow_runs and INSERT permissions on workflow_events."],"exampleFix":"// before\nawait resumeWorkflowRun(runId, cursor);\n// after\ntry {\n  await resumeWorkflowRun(runId, cursor);\n} catch (err) {\n  getLog().error({ err, runId }, 'resume_tx_failed');\n  throw err;\n}","handlingStrategy":"try-catch","validationCode":"// Check the run is still resumable before attempting the CAS resume\nconst status = await getWorkflowRunStatus(runId);\nif (status !== 'paused' && status !== 'failed') {\n  throw new Error(`run ${runId} is ${status ?? 'missing'}; not resumable`);\n}","typeGuard":"function isResumeTxError(err: unknown): err is Error & { cause?: unknown } {\n  return err instanceof Error && err.message.startsWith('Failed to resume workflow run:');\n}","tryCatchPattern":"try {\n  const result = await resumeWorkflowRun(runId, cursor);\n} catch (err) {\n  // Driver error inside the resume transaction; rollback already happened — retry is safe.\n  if (isTransient(err)) return retryResume(runId, cursor);\n  throw err;\n}","preventionTips":["Rely on the CAS: a retry after failure cannot double-claim the worktree.","Serialize admin actions and user resumes on the same run where possible.","Verify UPDATE/INSERT grants after DB role changes.","Watch db.workflow_run_resume_failed logs for deadlock patterns."],"tags":["database","transaction","compare-and-swap","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"}