{"record":{"id":"4f02fb9ad4336c44","repo":"vercel/ai","slug":"harness-claude-code-requires-a-json-schema-for-s","errorCode":null,"errorMessage":"Harness 'claude-code' requires a JSON schema for structured output.","messagePattern":"Harness 'claude-code' requires a JSON schema for structured output\\.","errorType":"exception","errorClass":"HarnessCapabilityUnsupportedError","httpStatus":null,"severity":"error","filePath":"packages/harness-claude-code/src/claude-code-harness.ts","lineNumber":1735,"sourceCode":"        ? {}\n        : {\n            submitUserMessage: async (text: string) => {\n              await userMessageSubmitter.submit(text);\n            },\n          }),\n      done,\n    };\n  };\n\n  return {\n    sessionId,\n    isResume,\n    doPromptTurn: async promptOpts => {\n      if (\n        promptOpts.responseFormat?.type === 'json' &&\n        promptOpts.responseFormat.schema == null\n      ) {\n        throw new HarnessCapabilityUnsupportedError({\n          message:\n            \"Harness 'claude-code' requires a JSON schema for structured output.\",\n          harnessId: 'claude-code',\n        });\n      }\n      await writeClaudeCodeSkills({\n        sandbox,\n        homeDir: sandboxHomeDir,\n        skills: promptOpts.skills,\n        abortSignal: promptOpts.abortSignal,\n      });\n      const control = wireTurn({\n        emit: promptOpts.emit,\n        abortSignal: promptOpts.abortSignal,\n      });\n\n      /*\n       * A signal that was already aborted has settled the turn inside","sourceCodeStart":1717,"sourceCodeEnd":1753,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/harness-claude-code/src/claude-code-harness.ts#L1717-L1753","documentation":"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.","triggerScenarios":"Calling the harness prompt path (doPromptTurn) with `responseFormat: { type: 'json' }` where `responseFormat.schema` is null or undefined.","commonSituations":"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.","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."],"exampleFix":"// before\nawait session.prompt({ prompt: 'List users', responseFormat: { type: 'json' } });\n// after\nawait session.prompt({\n  prompt: 'List users',\n  responseFormat: { type: 'json', schema: usersJsonSchema },\n});","handlingStrategy":"validation","validationCode":"function assertJsonResponseFormat(fmt) {\n  if (fmt && fmt.type === 'json' && fmt.schema == null) {\n    throw new Error('responseFormat.type=json requires a schema');\n  }\n}\nassertJsonResponseFormat(promptOpts.responseFormat);","typeGuard":"function hasJsonSchema(\n  rf: { type: 'json'; schema?: unknown } | undefined,\n): rf is { type: 'json'; schema: NonNullable<unknown> } {\n  return rf?.type === 'json' && rf.schema != null;\n}","tryCatchPattern":"try {\n  await harness.prompt({ prompt, responseFormat });\n} catch (e) {\n  if (HarnessCapabilityUnsupportedError.isInstance(e) && e.message.includes('JSON schema')) {\n    // retry with a schema or without responseFormat\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["structured-output","json","schema","validation"],"backgroundTag":"missing-json-schema","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}