{"record":{"id":"01b4ea0ebc98c33e","repo":"different-ai/openwork","slug":"workflow-recent-receipt-required","errorCode":"workflow_recent_receipt_required","errorMessage":"workflow_recent_receipt_required","messagePattern":"workflow_recent_receipt_required","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ee/apps/den-api/src/workflows.ts","lineNumber":620,"sourceCode":"    ) {\n      throw new Error(\"saved_workflow_plugin_context_required\")\n    }\n    await requirePluginArchResourceRole({\n      context: input.context,\n      resourceId: requestedPluginId,\n      resourceKind: \"plugin\",\n      role: \"editor\",\n    })\n  }\n  const receipts = await db.select().from(WorkflowRunTable).where(and(\n    eq(WorkflowRunTable.organization_id, organizationId),\n    eq(WorkflowRunTable.org_membership_id, ownerMemberId),\n    eq(WorkflowRunTable.code_digest, codemodeCodeDigest(input.workflow.code)),\n    eq(WorkflowRunTable.status, \"succeeded\"),\n    gt(WorkflowRunTable.finished_at, new Date(Date.now() - RECENT_RUN_WINDOW_MS)),\n  )).orderBy(desc(WorkflowRunTable.finished_at)).limit(1)\n  const receipt = receipts[0]\n  if (!receipt) throw new Error(\"workflow_recent_receipt_required\")\n\n  const built = await input.buildTools()\n  const manifestByPath = new Map(built.manifest.flatMap((entry) => [\n    [entry.scriptPath, entry] as const,\n    [entry.scriptPath.replace(/^tools\\./, \"\"), entry] as const,\n  ]))\n  const requiredCapabilities: Array<{ capabilityName: string; scriptPath: string }> = []\n  for (const call of parseCodemodeToolCalls(receipt.tool_calls)) {\n    const resolved = manifestByPath.get(call.name)\n    if (!resolved) throw new Error(`workflow_capability_unavailable:${call.name}`)\n    if (resolved.readOnly !== true) throw new Error(`workflow_requires_read_only_capabilities:${call.name}`)\n    if (!requiredCapabilities.some((entry) => entry.scriptPath === resolved.scriptPath)) {\n      requiredCapabilities.push({\n        capabilityName: resolved.capabilityName,\n        scriptPath: resolved.scriptPath,\n      })\n    }\n  }","sourceCodeStart":602,"sourceCodeEnd":638,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-api/src/workflows.ts#L602-L638","documentation":"Saving a workflow requires proof that the exact code being saved has actually run successfully recently in this organization by this member. saveWorkflow queries WorkflowRunTable for a succeeded run with a matching code digest finished within RECENT_RUN_WINDOW_MS; if no such receipt exists it throws 'workflow_recent_receipt_required'. This prevents saving untested or never-executed code as a reusable workflow.","triggerScenarios":"Calling saveWorkflow with workflow.code whose codemodeCodeDigest has no succeeded WorkflowRun row for the same organization_id, org_membership_id, finished within the recent-run window (e.g. the run failed, ran under a different member/org, or is older than the window).","commonSituations":"Editing code and saving before re-running it in the UI; the test run happened more than RECENT_RUN_WINDOW_MS ago; the run executed under a different member account; a failed or still-running run is the only record.","solutions":["Execute the workflow code successfully once before saving, with the same member and organization","Confirm the most recent succeeded run is within the recent-run window; re-run if stale","Make sure the code string is byte-identical to what ran (the digest must match — no whitespace-only edits between run and save)","Check that the run was recorded under the same ownerMemberId, not another membership"],"exampleFix":"// before\nconst result = await runCodemode(code) // run failed\nawait saveWorkflow({ workflow: { code, ... } }) // throws workflow_recent_receipt_required\n// after\nconst result = await runCodemode(code)\nif (!result.ok) throw new Error('fix code and re-run before saving')\nawait saveWorkflow({ workflow: { code, ... } })","handlingStrategy":"validation","validationCode":"async function hasRecentRunReceipt(code: string, organizationId: string, member: string) {\n  const rows = await db.select().from(WorkflowRunTable).where(and(\n    eq(WorkflowRunTable.organization_id, organizationId),\n    eq(WorkflowRunTable.org_membership_id, member),\n    eq(WorkflowRunTable.code_digest, codemodeCodeDigest(code)),\n    eq(WorkflowRunTable.status, 'succeeded'),\n    gt(WorkflowRunTable.finished_at, new Date(Date.now() - RECENT_RUN_WINDOW_MS)),\n  )).limit(1)\n  return rows.length > 0\n}","typeGuard":"null","tryCatchPattern":"try {\n  await saveWorkflow(input)\n} catch (err) {\n  if (err instanceof Error && err.message === 'workflow_recent_receipt_required') {\n    // surface 'run the workflow successfully, then save' to the user\n  }\n}","preventionTips":["Always run the exact code successfully immediately before saving","Avoid any edit (even whitespace) between the test run and the save — the digest must match","Make save-and-run an atomic UI flow rather than two independent actions","Watch for run/save happening under different member accounts in multi-account setups"],"tags":["workflows","validation","den-api","run-receipt"],"backgroundTag":"run-receipt-required","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}