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
- Re-run the workflow test with the current script so requiredCapabilities covers every tool call it makes.
- Add the missing tool path to requiredCapabilities (ensuring it is available and read-only).
- 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
- Regenerate requiredCapabilities by re-running tests whenever the script changes.
- Keep scripts free of conditional tool calls outside the declared set.
- Diff receipt.tool_calls against requiredCapabilities before registering.
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
- workflow_capability_unavailable
- workflow_requires_read_only_capabilities
- workflow_test_receipt_already_used
- workflow_snapshot_not_found
- invalid_mcp_connection_payload
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/86a840f4b28b084a.
Report an issue: GitHub.