{"record":{"id":"7fcc46a2bda6bb52","repo":"different-ai/openwork","slug":"workflow-test-receipt-already-used","errorCode":"workflow_test_receipt_already_used","errorMessage":"workflow_test_receipt_already_used","messagePattern":"workflow_test_receipt_already_used","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ee/apps/den-api/src/workflows.ts","lineNumber":410,"sourceCode":"    outputSchemaDigest === null\n      ? isNull(WorkflowRunTable.output_schema_digest)\n      : eq(WorkflowRunTable.output_schema_digest, outputSchemaDigest),\n    eq(WorkflowRunTable.status, \"succeeded\"),\n    isNull(WorkflowRunTable.artifact_content_deleted_at),\n    gt(WorkflowRunTable.finished_at, new Date(Date.now() - RECENT_RUN_WINDOW_MS)),\n  )).limit(1)\n  const receipt = receipts[0]\n  if (!receipt || receipt.renderer_version !== WORKFLOW_MARKDOWN_RENDERER_VERSION\n    || receipt.result_markdown === null || receipt.result_digest === null) {\n    throw new Error(\"workflow_matching_test_receipt_required\")\n  }\n\n  const consumed = await db.select({ id: ConfigObjectVersionTable.id }).from(ConfigObjectVersionTable).where(and(\n    eq(ConfigObjectVersionTable.organizationId, resource.configObject.organizationId),\n    eq(ConfigObjectVersionTable.configObjectId, resource.configObject.id),\n    eq(ConfigObjectVersionTable.sourceRevisionRef, receipt.id),\n  )).limit(1)\n  if (consumed[0]) throw new Error(\"workflow_test_receipt_already_used\")\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  for (const required of payload.parsed.requiredCapabilities) {\n    const current = manifestByPath.get(required.scriptPath)\n    if (!current || current.capabilityName !== required.capabilityName) {\n      throw new Error(`workflow_capability_unavailable:${required.scriptPath}`)\n    }\n    if (current.readOnly !== true) throw new Error(`workflow_requires_read_only_capabilities:${required.scriptPath}`)\n  }\n  for (const call of parseCodemodeToolCalls(receipt.tool_calls)) {\n    if (!payload.parsed.requiredCapabilities.some((required) => {\n      const normalized = call.name.replace(/^tools\\./, \"\")\n      return required.scriptPath === call.name || required.scriptPath.replace(/^tools\\./, \"\") === normalized\n    })) throw new Error(`workflow_test_capability_mismatch:${call.name}`)","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-api/src/workflows.ts#L392-L428","documentation":"This error is thrown in createWorkflowVersion when registering a workflow version from a test-run receipt. Each WorkflowRun receipt may be consumed at most once: before building, the code checks ConfigObjectVersionTable for any version whose sourceRevisionRef equals the receipt id, and throws if one exists. It prevents replaying the same test run to mint multiple workflow versions.","triggerScenarios":"Calling createWorkflowVersion (via the org workflow routes) with a receiptId that has already been used to register a prior workflow version — e.g. double-submitting the same test run, retrying a request that actually succeeded, or reusing an old receipt after the first registration succeeded but the client saw an error.","commonSituations":"Client retries without generating a new test run; front-end resubmits after timeout; replaying a saved receipt id in a script or migration.","solutions":["Generate and run a fresh workflow test to obtain a new receipt id before registering a version.","Look up the existing ConfigObjectVersion row via sourceRevisionRef = receipt.id and use it instead of registering again.","Make registration idempotent on the client: check whether the version already exists before calling createWorkflowVersion."],"exampleFix":"// before\nawait createWorkflowVersion({ receiptId: existingReceipt.id, ... })\n// after\nconst [consumed] = await db.select().from(ConfigObjectVersionTable)\n  .where(eq(ConfigObjectVersionTable.sourceRevisionRef, existingReceipt.id))\nif (!consumed) {\n  await createWorkflowVersion({ receiptId: existingReceipt.id, ... })\n}","handlingStrategy":"try-catch","validationCode":"const [existing] = await db.select({ id: ConfigObjectVersionTable.id })\n  .from(ConfigObjectVersionTable)\n  .where(eq(ConfigObjectVersionTable.sourceRevisionRef, receipt.id)).limit(1)\nconst usable = !existing","typeGuard":null,"tryCatchPattern":"try {\n  await createWorkflowVersion({ receiptId, ... })\n} catch (e) {\n  if (e.message === \"workflow_test_receipt_already_used\") {\n    // treat as success: version already registered from this receipt\n  } else throw e\n}","preventionTips":["Make client registration calls idempotent keyed on receipt id.","Never retry with the same receipt id without checking for an existing version.","Always run a fresh test to obtain a new receipt before each registration."],"tags":["workflow","idempotency","receipt-reuse","den-api"],"backgroundTag":"resource-already-consumed","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}