vercel/ai · error · HarnessCapabilityUnsupportedError
Harness 'cline' requires a JSON schema for structured output
Error message
Harness 'cline' requires a JSON schema for structured output.
What it means
When responseFormat.type is 'json', the Cline harness requires an explicit JSON schema because structured output is implemented through tools, which need a schema to shape the tool input. If schema is null/undefined, a HarnessCapabilityUnsupportedError is thrown naming the 'cline' harness. This is a capability check, not a data validation failure.
Source
Thrown at packages/harness-cline/src/cline-session.ts:586
tools: ReadonlyArray<HarnessV1ToolSpec>;
instructions?: string;
emit: (part: HarnessV1StreamPart) => void;
abortSignal?: AbortSignal;
responseFormat?: HarnessV1PromptTurnOptions['responseFormat'];
}): Promise<HarnessV1PromptControl> {
if (stopped) {
throw new Error('Cline session has been stopped.');
}
const userTools = turnOpts.tools;
const skillsRuntime = createClineSkillsRuntime({
skills: turnOpts.skills,
});
if (
turnOpts.responseFormat?.type === 'json' &&
turnOpts.responseFormat.schema == null
) {
throw new HarnessCapabilityUnsupportedError({
message:
"Harness 'cline' requires a JSON schema for structured output.",
harnessId: HARNESS_ID,
});
}
if (
turnOpts.responseFormat?.type === 'json' &&
agentModel.providerId === 'openai-codex-cli'
) {
throw new HarnessCapabilityUnsupportedError({
message:
"Harness 'cline' cannot require structured output with the openai-codex-cli provider because that provider does not expose external tools.",
harnessId: HARNESS_ID,
});
}
if (turnOpts.model != null && turnOpts.model !== activeModelId) {
activeModelId = turnOpts.model;View on GitHub (pinned to 69428b1f8b)
Solutions
- Provide a JSON schema: responseFormat: { type: 'json', schema: zodSchema(responseFormatSchema) } or an equivalent JSON Schema object.
- If no schema exists, drop responseFormat entirely and parse/validate the model's text output yourself.
- Check the resolved object at runtime (schema != null) before passing responseFormat to the session.
Example fix
// before
await session.prompt({ text: 'Return JSON', responseFormat: { type: 'json' } });
// after
await session.prompt({ text: 'Return JSON', responseFormat: { type: 'json', schema: z.object({ answer: z.string() }) } }); Defensive patterns
Strategy: validation
Validate before calling
function assertValidJsonResponseFormat(rf?: { type?: string; schema?: unknown }) {
if (rf?.type === 'json' && rf.schema == null) {
throw new Error('responseFormat.type=json requires responseFormat.schema');
}
}
assertValidJsonResponseFormat(turnOpts.responseFormat); Try / catch
try {
await session.prompt(turnOpts);
} catch (e) {
if (HarnessCapabilityUnsupportedError.isInstance(e) && e.message.includes('requires a JSON schema')) {
turnOpts = { ...turnOpts, responseFormat: { ...turnOpts.responseFormat!, schema: zodSchema(DefaultSchema) } };
await session.prompt(turnOpts);
} else throw e;
} Prevention
- Build responseFormat objects through a helper that always pairs type:'json' with a schema.
- Convert zod schemas via zodSchema() once and assert the result is non-null before passing.
- Add a type-level requirement: define your responseFormat type so schema is required when type is 'json' (discriminated union).
When it happens
Trigger: Calling prompt/continueTurn with responseFormat: { type: 'json' } but omitting responseFormat.schema, e.g. responseFormat: { type: 'json', schema: undefined }.
Common situations: Assuming the harness can infer a schema; porting code from another harness/provider that accepts schemaless JSON mode; building responseFormat dynamically and the schema variable being undefined due to a failed zod-to-schema conversion.
Related errors
- Harness 'claude-code' requires a JSON schema for structured
- Harness 'cline' cannot require structured output with the op
- cline: manual compaction is not supported by the standalone
- Harness 'pi' does not support structured output.
- No object generated: could not parse the response.
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/35eacfbc71cd1040.
Report an issue: GitHub.