different-ai/openwork · error
automation_cloud_result_not_durable
automation_cloud_result_not_durable
Error message
automation_cloud_result_not_durable
What it means
When completeCloud finishes a run with updateArtifactState === false it skips the artifact-state update and instead re-reads the run via runById; if that read returns nothing the repository cannot prove the just-completed run is durable and throws automation_cloud_result_not_durable. It is a read-back assertion guarding the completion path.
Source
Thrown at ee/apps/den-api/src/automations/repository.ts:718
usage: input.usage ?? emptyUsage,
error: input.error,
now: input.now,
})
await db.update(AutomationRunTable).set({
codemode_receipt_id: input.codemodeReceiptId ? normalizeDenTypeId("workflowRun", input.codemodeReceiptId) : null,
validated_result: input.validatedResult,
updated_at: new Date(input.now),
}).where(eq(AutomationRunTable.id, normalizeRunId(input.runId)))
const artifactState = cloudArtifactStateUpdate({
runId: input.runId,
result: input.status === "succeeded"
? { ok: true, value: input.validatedResult }
: { ok: false, message: input.error?.message ?? input.resultSummary },
now: input.now,
})
if (input.updateArtifactState === false) {
const refreshed = await this.runById(completed.id)
if (!refreshed) throw new Error("automation_cloud_result_not_durable")
return refreshed
}
if (artifactState.kind === "succeeded") {
await db.update(AutomationTable).set({
latest_successful_run_id: normalizeRunId(artifactState.latestSuccessfulRunId),
latest_successful_result: artifactState.latestSuccessfulResult,
state: artifactState.state,
needs_attention_reason: artifactState.needsAttentionReason,
updated_at: new Date(input.now),
}).where(eq(AutomationTable.id, normalizeAutomationId(input.automationId)))
} else {
await db.update(AutomationTable).set({
state: artifactState.state,
needs_attention_reason: artifactState.needsAttentionReason,
updated_at: new Date(input.now),
}).where(eq(AutomationTable.id, normalizeAutomationId(input.automationId)))
}
const refreshed = await this.runById(completed.id)View on GitHub (pinned to 2b7df46e8a)
Solutions
- Confirm runById returns the completed run directly — investigate why read-after-write fails (read replicas, RLS, connection routing)
- Check that the runId used for completion and read-back is identical after normalization
- Look for concurrent jobs/cron cleanup that may delete automation_runs rows immediately
- Retry completeCloud once; if persistent, treat the run record as lost and alert rather than silently returning
Example fix
// before
await repo.completeCloud({ runId, updateArtifactState: false, ... })
// after
try {
await repo.completeCloud({ runId, updateArtifactState: false, ... })
} catch (e) {
if (String(e?.message).includes('not_durable')) {
const run = await repo.runById(runId)
console.error(`completed run ${runId} not readable afterwards:`, !!run)
}
throw e
} Defensive patterns
Strategy: try-catch
Validate before calling
const check = await repo.runById(runId)
if (!check) throw new Error(`run ${runId} not readable before completion`) Type guard
function runExists(run: { id: string } | null | undefined): run is { id: string } {
return typeof run === 'object' && run !== null && typeof run.id === 'string'
} Try / catch
try {
await repo.completeCloud({ ...input, updateArtifactState: false })
} catch (e) {
if (String((e as Error)?.message) === 'automation_cloud_result_not_durable') {
// investigate read-after-write failure; do not silently swallow
} else throw e
} Prevention
- Avoid updateArtifactState:false unless you have a reason; let the repository manage artifact state
- Ensure runById and the transaction share the same DB connection/read concern (no replica lag)
- Check for cleanup jobs that could delete runs concurrently with completion
When it happens
Trigger: Calling completeCloud with updateArtifactState:false and then runById(completed.id) returns undefined — the run row vanished or the id normalization diverged between the insert path and the lookup.
Common situations: Misconfigured database hiding the freshly written row (replica reads, RLS); run id transformed inconsistently by normalizeRunId; concurrent delete of the run row between completion and read-back.
Related errors
- OpenWork server unavailable. Connect to manage imported clou
- OpenWork server unavailable. Connect to manage imported clou
- automation_revision_changed
- invalid_cached_app
- organization_not_found
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/3f7ff5446dfdb49d.
Report an issue: GitHub.