Skip to content

convertConstToEnum emits non-string enum values (const: false -> enum: [false]); Gemini rejects with 400 TYPE_STRING #17

Closed

Description

@willowite

Summary

convertConstToEnum() turns every const into enum: [value], including boolean and number constants. Gemini accepts only string enum values, so any request that carries a tool with const: true / const: false (common in discriminated unions from MCP tools) is rejected with HTTP 400 before the model runs.

Error

Invalid value at 'request.tools[0].function_declarations[194].parameters.properties[0].value.items.any_of[0].properties[12].value.enum[0]' (TYPE_STRING), false
Invalid value at 'request.tools[0].function_declarations[195].parameters.properties[0].value.items.one_of[0].properties[10].value.properties[0].value.enum[0]' (TYPE_STRING), true
... (18 lines like this per request)
Status: 400

Every request with the full tool set fails, so the model is unusable as a subagent until the offending tools are removed.

Where

packages/opencode/src/plugin/request-helpers.ts, convertConstToEnum() on main:

if (key === 'const' && !schema.enum) {
  result.enum = [value]   // value may be boolean or number
}

Repro

Any tool whose JSON schema contains { "const": false } (or true, or a number), for example:

{ "type": "object", "properties": { "flag": { "const": false } } }

sent to google/antigravity-gemini-3.8-flash (effective gemini-3.8-flash-high).

Suggested fix

Convert only string constants, and leave non-string const without an enum (Gemini keeps the declared type):

if (key === 'const' && !schema.enum) {
  if (typeof value === 'string') {
    result.enum = [value]
  }
}

I run this change locally on 2.2.1 and the same tool set is accepted.

Environment

  • @cortexkit/opencode-antigravity-auth 2.2.1 (latest on npm)
  • OpenCode 1.18.31, Windows 11

Activity

  1. willowite commented on Sep 30, 2026

    @willowite
    Author

    A source-level follow-up: please cover both schema adapters, not only const conversion in the OpenCode package.

    The current packages/core/src/transform/gemini.ts also retains non-string enum values:

    } else if (key === 'enum' && Array.isArray(value)) {
      // Keep enum values as-is
      result[key] = value
    }

    In packages/opencode/src/plugin/request-helpers.ts, convertConstToEnum still unconditionally produces result.enum = [value].

    Suggested upstream changes

    For the Gemini schema boundary, retain an enum only when every value is a string. Do not stringify boolean or numeric values while keeping the original declared type.

         } else if (key === 'enum' && Array.isArray(value)) {
    -      // Keep enum values as-is
    -      result[key] = value
    +      if (value.every((entry) => typeof entry === 'string')) {
    +        result[key] = value
    +      }

    In convertConstToEnum, guard newly created enums and existing enum arrays:

         if (key === 'const' && !schema.enum) {
    -      result.enum = [value]
    +      if (typeof value === 'string') result.enum = [value]
    +    } else if (key === 'enum' && Array.isArray(value)) {
    +      if (value.every((entry) => typeof entry === 'string')) result.enum = value
         } else {
           result[key] = convertConstToEnum(value)

    I exercised the public convertConstToEnum function and this change in isolation with synthetic inputs:

    • Boolean const: false: currently becomes enum: [false]; proposed change retains type: "boolean" without an invalid enum.
    • Numeric enum: [1, 2]: proposed change omits the unsupported enum.
    • String const and string enum: unchanged.
    • Nested boolean enum under an object property: also handled.

    This is not an end-to-end Gemini request test. Omitting an unsupported constraint broadens the provider-side schema, so the original tool's validation must remain authoritative. The same cases should be added to both adapters' tests.

    Sources

  2. agauth-alfonso commented on Oct 13, 2026

    @agauth-alfonso

    Confirmed still present in 3.0.2. convertConstToEnum emits enum: [value] for any type (request-helpers.ts), and core's toGeminiSchema keeps enum values as they are (gemini.ts). We plan one schema fix covering this, #27 and #30.

  3. agauth-alfonso commented on Oct 13, 2026

    @agauth-alfonso

    Fixed in 3.0.3. Boolean and number constants and enums are no longer sent as enum values; the allowed value is described to the model and the parameter keeps its real type, so these schemas no longer fail with TYPE_STRING. Thank you for the detailed report and the exact error path. Please reopen if you still see it on @cortexkit/opencode-antigravity-auth@latest.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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