vercel/ai · error · HarnessCapabilityUnsupportedError
Harness 'claude-code' requires a JSON schema for structured
Error message
Harness 'claude-code' requires a JSON schema for structured output.
What it means
The claude-code harness maps structured output onto the Claude CLI's schema support, which requires a JSON schema to constrain the model's response. When a prompt turn requests `responseFormat: { type: 'json' }` without a `schema`, the harness throws HarnessCapabilityUnsupportedError because free-form 'json' output cannot be reliably produced.
Source
Thrown at packages/harness-claude-code/src/claude-code-harness.ts:1735
? {}
: {
submitUserMessage: async (text: string) => {
await userMessageSubmitter.submit(text);
},
}),
done,
};
};
return {
sessionId,
isResume,
doPromptTurn: async promptOpts => {
if (
promptOpts.responseFormat?.type === 'json' &&
promptOpts.responseFormat.schema == null
) {
throw new HarnessCapabilityUnsupportedError({
message:
"Harness 'claude-code' requires a JSON schema for structured output.",
harnessId: 'claude-code',
});
}
await writeClaudeCodeSkills({
sandbox,
homeDir: sandboxHomeDir,
skills: promptOpts.skills,
abortSignal: promptOpts.abortSignal,
});
const control = wireTurn({
emit: promptOpts.emit,
abortSignal: promptOpts.abortSignal,
});
/*
* A signal that was already aborted has settled the turn insideView on GitHub (pinned to 69428b1f8b)
Solutions
- Always supply a schema when using `responseFormat: { type: 'json' }` (a JSON Schema object describing the expected output).
- If you do not need structured output, remove the responseFormat option entirely instead of using type 'json' without a schema.
- Use a zod schema converted with the SDK's jsonSchema/zodSchema helper to generate the schema value.
Example fix
// before
await session.prompt({ prompt: 'List users', responseFormat: { type: 'json' } });
// after
await session.prompt({
prompt: 'List users',
responseFormat: { type: 'json', schema: usersJsonSchema },
}); Defensive patterns
Strategy: validation
Validate before calling
function assertJsonResponseFormat(fmt) {
if (fmt && fmt.type === 'json' && fmt.schema == null) {
throw new Error('responseFormat.type=json requires a schema');
}
}
assertJsonResponseFormat(promptOpts.responseFormat); Type guard
function hasJsonSchema(
rf: { type: 'json'; schema?: unknown } | undefined,
): rf is { type: 'json'; schema: NonNullable<unknown> } {
return rf?.type === 'json' && rf.schema != null;
} Try / catch
try {
await harness.prompt({ prompt, responseFormat });
} catch (e) {
if (HarnessCapabilityUnsupportedError.isInstance(e) && e.message.includes('JSON schema')) {
// retry with a schema or without responseFormat
}
throw e;
} Prevention
- Make schema a required field in your internal responseFormat helper type.
- Use zod schemas converted via jsonSchema() so a schema is always generated.
- Add a lint/test that no call site passes type:'json' without schema.
- Drop responseFormat entirely when structured output is unnecessary.
When it happens
Trigger: Calling the harness prompt path (doPromptTurn) with `responseFormat: { type: 'json' }` where `responseFormat.schema` is null or undefined.
Common situations: Porting code from another harness/provider that accepts schema-less JSON mode; building responseFormat dynamically and omitting schema; SDK type changes after an upgrade where schema became mandatory for json type.
Related errors
- Invalid host tool catalog.
- Invalid host tool relay request.
- Harness 'cline' requires a JSON schema for structured output
- Invalid AI SDK harness skills manifest: ${manifestPath}
- maxEmbeddingsPerCall must be greater than 0
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/4f02fb9ad4336c44.
Report an issue: GitHub.