different-ai/openwork · error

workflow_test_receipt_already_used

workflow_test_receipt_already_used

Error message

workflow_test_receipt_already_used

What it means

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.

Source

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

    outputSchemaDigest === null
      ? isNull(WorkflowRunTable.output_schema_digest)
      : eq(WorkflowRunTable.output_schema_digest, outputSchemaDigest),
    eq(WorkflowRunTable.status, "succeeded"),
    isNull(WorkflowRunTable.artifact_content_deleted_at),
    gt(WorkflowRunTable.finished_at, new Date(Date.now() - RECENT_RUN_WINDOW_MS)),
  )).limit(1)
  const receipt = receipts[0]
  if (!receipt || receipt.renderer_version !== WORKFLOW_MARKDOWN_RENDERER_VERSION
    || receipt.result_markdown === null || receipt.result_digest === null) {
    throw new Error("workflow_matching_test_receipt_required")
  }

  const consumed = await db.select({ id: ConfigObjectVersionTable.id }).from(ConfigObjectVersionTable).where(and(
    eq(ConfigObjectVersionTable.organizationId, resource.configObject.organizationId),
    eq(ConfigObjectVersionTable.configObjectId, resource.configObject.id),
    eq(ConfigObjectVersionTable.sourceRevisionRef, receipt.id),
  )).limit(1)
  if (consumed[0]) throw new Error("workflow_test_receipt_already_used")

  const built = await input.buildTools()
  const manifestByPath = new Map(built.manifest.flatMap((entry) => [
    [entry.scriptPath, entry] as const,
    [entry.scriptPath.replace(/^tools\./, ""), entry] as const,
  ]))
  for (const required of payload.parsed.requiredCapabilities) {
    const current = manifestByPath.get(required.scriptPath)
    if (!current || current.capabilityName !== required.capabilityName) {
      throw new Error(`workflow_capability_unavailable:${required.scriptPath}`)
    }
    if (current.readOnly !== true) throw new Error(`workflow_requires_read_only_capabilities:${required.scriptPath}`)
  }
  for (const call of parseCodemodeToolCalls(receipt.tool_calls)) {
    if (!payload.parsed.requiredCapabilities.some((required) => {
      const normalized = call.name.replace(/^tools\./, "")
      return required.scriptPath === call.name || required.scriptPath.replace(/^tools\./, "") === normalized
    })) throw new Error(`workflow_test_capability_mismatch:${call.name}`)

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Generate and run a fresh workflow test to obtain a new receipt id before registering a version.
  2. Look up the existing ConfigObjectVersion row via sourceRevisionRef = receipt.id and use it instead of registering again.
  3. Make registration idempotent on the client: check whether the version already exists before calling createWorkflowVersion.

Example fix

// before
await createWorkflowVersion({ receiptId: existingReceipt.id, ... })
// after
const [consumed] = await db.select().from(ConfigObjectVersionTable)
  .where(eq(ConfigObjectVersionTable.sourceRevisionRef, existingReceipt.id))
if (!consumed) {
  await createWorkflowVersion({ receiptId: existingReceipt.id, ... })
}
Defensive patterns

Strategy: try-catch

Validate before calling

const [existing] = await db.select({ id: ConfigObjectVersionTable.id })
  .from(ConfigObjectVersionTable)
  .where(eq(ConfigObjectVersionTable.sourceRevisionRef, receipt.id)).limit(1)
const usable = !existing

Try / catch

try {
  await createWorkflowVersion({ receiptId, ... })
} catch (e) {
  if (e.message === "workflow_test_receipt_already_used") {
    // treat as success: version already registered from this receipt
  } else throw e
}

Prevention

When it happens

Trigger: 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.

Common situations: Client retries without generating a new test run; front-end resubmits after timeout; replaying a saved receipt id in a script or migration.

Related errors


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