different-ai/openwork · error

workflow_test_capability_mismatch

workflow_test_capability_mismatch

Error message

workflow_test_capability_mismatch:${call.name}

What it means

Thrown in createWorkflowVersion when a tool call recorded in the test receipt (receipt.tool_calls) does not correspond to any entry in payload.parsed.requiredCapabilities, after normalizing the 'tools.' prefix. The declared capability list and the calls actually made during the test run must agree exactly.

Source

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

  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}`)
  }

  const now = new Date()
  const configObjectVersionId = createDenTypeId("configObjectVersion")
  await db.transaction(async (tx) => {
    await tx.insert(ConfigObjectVersionTable).values({
      id: configObjectVersionId,
      organizationId: resource.configObject.organizationId,
      configObjectId: resource.configObject.id,
      normalizedPayloadJson: payload.value,
      rawSourceText: input.draft.code,
      schemaVersion: "codemode-script-v1",
      createdVia: "cloud",
      createdByOrgMembershipId: input.context.organizationContext.currentMember.id,
      sourceRevisionRef: receipt.id,
      isDeletedVersion: false,
      createdAt: now,
    })

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Re-run the workflow test with the current script so requiredCapabilities covers every tool call it makes.
  2. Add the missing tool path to requiredCapabilities (ensuring it is available and read-only).
  3. Remove or guard the extra tool call in the workflow script.

Example fix

// before
requiredCapabilities: [{ scriptPath: "tools.search.web", capabilityName: "webSearch" }]
// script also calls tools.docs.list
// after
requiredCapabilities: [
  { scriptPath: "tools.search.web", capabilityName: "webSearch" },
  { scriptPath: "tools.docs.list", capabilityName: "docsList" },
]
Defensive patterns

Strategy: validation

Validate before calling

const calls = parseCodemodeToolCalls(receipt.tool_calls).map(c => c.name)
const declared = new Set(requiredCapabilities.flatMap(r => [r.scriptPath, r.scriptPath.replace(/^tools\./, "")]))
const undeclared = calls.filter(name => !declared.has(name) && !declared.has(name.replace(/^tools\./, "")))
if (undeclared.length) throw new Error(`undeclared calls: ${undeclared}`)

Try / catch

try {
  await createWorkflowVersion(input)
} catch (e) {
  if (String(e.message).startsWith("workflow_test_capability_mismatch:")) {
    const tool = e.message.split(":")[1]
    // declare `tool` in requiredCapabilities or remove the call
  } else throw e
}

Prevention

When it happens

Trigger: Registering a workflow where the test run invoked a tool that is not declared in requiredCapabilities — e.g. capabilities were edited after the test ran, or the script changed between test and registration.

Common situations: Hand-editing the workflow payload to trim capability declarations; a script that conditionally calls extra tools; stale test receipt from an older script revision.

Related errors


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