different-ai/openwork · error

workflow_snapshot_not_found

workflow_snapshot_not_found

Error message

workflow_snapshot_not_found

What it means

Thrown in deleteWorkflowSnapshotContent when no WorkflowRun row matches the given receiptId scoped to the config object's organization and id with a non-null config_object_version_id. The caller asked to delete (redact) a snapshot's content, but no corresponding workflow snapshot exists.

Source

Thrown at ee/apps/den-api/src/workflows.ts:472

  })
  return getWorkflowDetail({ context: input.context, configObjectId: resource.configObject.id })
}

export async function deleteWorkflowSnapshotContent(input: {
  context: PluginArchActorContext
  configObjectId: string
  receiptId: string
}) {
  const resource = await workflowResource(input.context, input.configObjectId, "manager")
  const receiptId = parseReceiptId(input.receiptId)
  const rows = await db.select().from(WorkflowRunTable).where(and(
    eq(WorkflowRunTable.id, receiptId),
    eq(WorkflowRunTable.organization_id, resource.configObject.organizationId),
    eq(WorkflowRunTable.config_object_id, resource.configObject.id),
    isNotNull(WorkflowRunTable.config_object_version_id),
  )).limit(1)
  const receipt = rows[0]
  if (!receipt) throw new Error("workflow_snapshot_not_found")
  if (!receipt.artifact_content_deleted_at) {
    await db.update(WorkflowRunTable).set({
      script_input: null,
      validated_result: null,
      result_markdown: null,
      artifact_content_deleted_at: new Date(),
    }).where(eq(WorkflowRunTable.id, receipt.id))
  }

  if (receipt.automation_run_id) {
    const automationRuns = await db.select({ automationId: AutomationRunTable.automation_id })
      .from(AutomationRunTable)
      .where(eq(AutomationRunTable.id, receipt.automation_run_id)).limit(1)
    const automationId = automationRuns[0]?.automationId
    if (automationId) {
      const retained = await db.select({ receipt: WorkflowRunTable, run: AutomationRunTable })
        .from(WorkflowRunTable)
        .innerJoin(AutomationRunTable, eq(AutomationRunTable.id, WorkflowRunTable.automation_run_id))

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Verify the receiptId belongs to the same organization and config object as the route's resource.
  2. Check the row is a test-run snapshot (config_object_version_id IS NOT NULL) before calling deletion.
  3. Treat the error as not-found: skip or log instead of retrying with the same id.

Example fix

// before
await deleteWorkflowSnapshot(receiptId) // any id
// after
const [run] = await db.select().from(WorkflowRunTable)
  .where(and(eq(WorkflowRunTable.id, receiptId), isNotNull(WorkflowRunTable.config_object_version_id)))
if (run) await deleteWorkflowSnapshot(receiptId)
Defensive patterns

Strategy: try-catch

Validate before calling

const [run] = await db.select({ id: WorkflowRunTable.id }).from(WorkflowRunTable)
  .where(and(eq(WorkflowRunTable.id, receiptId),
    eq(WorkflowRunTable.organization_id, orgId),
    eq(WorkflowRunTable.config_object_id, configObjectId),
    isNotNull(WorkflowRunTable.config_object_version_id))).limit(1)
const exists = !!run

Try / catch

try {
  await deleteWorkflowSnapshot(receiptId)
} catch (e) {
  if (e.message === "workflow_snapshot_not_found") {
    // already gone or wrong id: log and continue
  } else throw e
}

Prevention

When it happens

Trigger: Calling the snapshot deletion route with a receiptId that does not exist, belongs to another org/config object, or whose row has a NULL config_object_version_id (i.e. not a version-producing test run); also firing the request twice after the first deletion partially succeeded — actually deletion is idempotent once found, so repeats mainly fail on wrong ids.

Common situations: Already-deleted or pruned workflow runs; typos or stale ids in cleanup scripts; passing an id from a different organization after an org switch in the client.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/1c96865d9859398e. Report an issue: GitHub.