Skip to content

fix(util): drop null and empty enum values for Gemini schemas#4545

Open
RsLuna7 wants to merge 1 commit into
router-for-me:devfrom
RsLuna7:pr/gemini-schema-null-enum
Open

fix(util): drop null and empty enum values for Gemini schemas#4545
RsLuna7 wants to merge 1 commit into
router-for-me:devfrom
RsLuna7:pr/gemini-schema-null-enum

Conversation

@RsLuna7

@RsLuna7 RsLuna7 commented Jul 24, 2026

Copy link
Copy Markdown

Problem

Gemini rejects a request with enum[n]: cannot be empty (HTTP 400) whenever a tool schema declares an optional enum the JSON Schema way, i.e. with null listed among the allowed values:

{
  "status": {
    "type": ["string", "null"],
    "enum": ["pending", "in_progress", "completed", "cancelled", null]
  }
}

This shape is not exotic — it is what several schema generators emit for an optional enum field (for example Rust's schemars for Option<SomeEnum>), so any client whose tool definitions contain a nullable enum hits the 400 and the whole request fails, not just the affected property.

Cause

convertEnumValuesToStrings in internal/util/gemini_schema.go normalizes every enum entry with gjson.Result.String(). For a JSON null that returns "", so the empty string is written straight back into the enum array and forwarded to Gemini, which only accepts non-empty strings there.

Fix

  • Skip null and empty entries while normalizing.
  • If nothing valid remains after filtering, delete the enum keyword instead of emitting an empty array, so the property degrades to a plain typed field rather than an invalid empty enum.

convertEnumValuesToStrings runs before addEnumHints, so the hint text generated downstream no longer picks up empty values either — no separate change needed there.

Tests

Adds TestCleanJSONSchemaForAntigravity_RemovesNullAndEmptyEnumValues, built from two schemas that actually triggered the 400 in the field: a nullable todos[].status and a nullable capability_mode. It asserts the filtered enums keep exactly their valid values and that no entry is a non-string or an empty string.

Verification

  • go test ./internal/util -count=1 — ok
  • go build -o test-output ./cmd/server — ok
  • gofmt — clean on both changed files

JSON Schema allows null inside an enum array to express an optional
value, but Gemini only accepts non-empty strings there and rejects the
whole request with "enum[n]: cannot be empty" (HTTP 400).

convertEnumValuesToStrings walked the array with gjson.Result.String(),
which renders a JSON null as "", so the empty string was passed straight
through to Gemini. Skip null and empty entries instead, and delete the
enum keyword altogether when no valid value remains, so the property
degrades to a plain typed field rather than an invalid empty enum.

Covered by a regression test built from two schemas that actually
triggered the 400: a nullable todos[].status and a nullable
capability_mode.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant