Skip to content

Gemini: Switch structured output from response_schema to response_json_schema to support full JSON Schema #974

@cainydev

Description

@cainydev

Summary

Prism currently sends structured output schemas to Gemini using the response_schema field (a proto-based API field). Gemini also exposes a newer response_json_schema field that accepts a richer subset of JSON Schema. Switching to response_json_schema fixes two real-world schema shapes that currently cause 400 INVALID_ARGUMENT errors with response_schema.

The two rejected fields

1. additionalProperties

When a schema contains additionalProperties: false on a nested object (e.g. inside items), Gemini returns:

Unknown name "additionalProperties" at 'generation_config.response_schema.properties[0].value.items': Cannot find field.

SchemaMap::toArray() already strips additionalProperties and name from the top-level array (line 28), but it can only recurse into properties/items when the schema is a native Prism ObjectSchema/ArraySchema. Custom schema implementations that implement HasSchemaType and serialize to a flat array via toArray() bypass the recursion, so nested additionalProperties passes through to the proto field and causes the 400.

2. Nullable union types ("type": ["string", "null"])

When a property is nullable, JSON Schema represents it as "type": ["string", "null"]. response_schema is a proto field that does not accept arrays for type, returning:

Unknown name "type" at '...': Proto field is not repeating, cannot start list.

Root cause

response_schema is a protobuf-mapped field with a strict subset of JSON Schema. response_json_schema is a newer field that accepts standard JSON Schema directly, without the proto restrictions.

Verification

Tested directly against the Gemini REST API with both field names using gemini-2.5-flash, gemini-2.5-flash-lite, and gemini-3.1-flash-lite-preview:

Field additionalProperties: false in nested object "type": ["string", "null"]
response_schema ❌ 400 INVALID_ARGUMENT ❌ 400 INVALID_ARGUMENT
response_json_schema ✅ 200 ✅ 200

response_json_schema works on all three models tested — it is not limited to Gemini 3.x.

Proposed fix

In Structured.php line 131, change:

'response_schema' => (new SchemaMap($request->schema()))->toArray(),

to:

'response_json_schema' => (new SchemaMap($request->schema()))->toArray(),

This is a one-line change. SchemaMap output is valid JSON Schema and passes through correctly under response_json_schema.

It may also be worth checking whether SchemaMap still needs to strip additionalProperties and name once response_json_schema is used, those fields are accepted by response_json_schema so the stripping in toArray() line 28 could potentially be relaxed, though keeping it is harmless.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions