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

  1. Provide a JSON schema: responseFormat: { type: 'json', schema: zodSchema(responseFormatSchema) } or an equivalent JSON Schema object.
  2. If no schema exists, drop responseFormat entirely and parse/validate the model's text output yourself.
  3. 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

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


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/35eacfbc71cd1040. Report an issue: GitHub.