[GH-ISSUE #4025] [Bug] Gemini-backed clients reject the whole tool catalog: advertised schemas emit non-string const values (boolean enum MUST be TYPE_STRING) #1601

Closed
opened 2026-10-16 21:07:46 +00:00 by bsakaguchi · 4 comments
Owner

Originally created by @carcraze on GitHub (Oct 15, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/4025

Summary

rea's advertised tool input schemas emit non-string const values (booleans) on 5 tools. Clients that render declarations through the Vercel AI SDK serialize those as enum: [false] / enum: [true], and Google's functionDeclarations[].parameters accepts only string enum values — so the entire request fails with HTTP 400 while REA is connected. Every Gemini model in the client becomes unusable; other providers on the same client work fine.

This is the same whole-catalog failure shape as #2832 (dependentRequired, fixed in 6.5.0), #2999, #2813, #1484: one offending advertisement takes down all tools, not just the offending one.

Environment

rea-agents 6.4.0 (observed failure); same constructs verified in 6.5.0 advertised tools/list
Node v24.21.0
Client opencode 1.18.32, Google Gemini provider (every Gemini model fails)
Transport MCP stdio, npx -y rea-agents@<version> mcp

Observed error

Invalid value at 'tools[0].function_declarations[112].parameters.properties[3].value.any_of[0].enum[0]' (TYPE_STRING), false
Invalid value at 'tools[0].function_declarations[112].parameters.properties[3].value.any_of[1].enum[0]' (TYPE_STRING), true
  • 100% reproducible while REA is connected; the same request is accepted as soon as REA is removed from the session.
  • The named property is a boolean anyOf (4th property of declaration 112). The shape matches inspect_electron_page.inputSchema.properties.include_script_sources (anyOf[0].const = false, anyOf[1].const = true). The declaration index depends on the full catalog, so I mark the exact declaration as consistent-with, not proven.

Where the values are advertised (observed)

Method: MCP stdio handshake (initialize → notifications/initialized → tools/list), then a recursive walk of every inputSchema collecting const/enum values that are not strings. No non-string enum was found — only boolean const.

rea-agents@6.5.0 — 207 tools, 5 with non-string const, 38 occurrences:

tool consts representative paths
inspect_electron_page 4 properties.include_script_sources.anyOf[0/1], $defs.__schema0/__schema4.properties.include_script_sources
inspect_web_page 2 $defs.__schema11 (false), $defs.__schema13 (true), referenced from include_script_sources.anyOf
analyze_web_bundle 1 $defs.__schema10.const = true
compare_web_captures 30 before/after.inspection.scripts…source.oneOf[*].properties.included, …network.prior_activity_available, …metadata.headers_allowlisted, …storage.values_redacted, …completeness.oneOf[*].properties.equality_eligible
evaluate_reconstruction_coverage 1 properties.coverage.properties.verifier_contracts.items.properties.normalization_removes_dimensions.const = false

rea-agents@6.4.0 — 170 tools, the same 5 tools, 17 occurrences (same constraints, referenced via $defs instead of inlined where noted above).

REA_MCP_INPUT_SCHEMA_PROFILE=compact does not fully avoid it: the inline projection keeps const; the boolean values disappear only where the shallow reduction applies (observed on 6.5.0 — small schemas such as inspect_electron_page still advertise the anyOf-of-const form).

Happy to paste the ~60-line scan script in a comment if it helps.

Why the whole catalog fails

Source-derived: these consts originate from canonical Zod literals (z.literal(false) / z.literal(true)) in discriminated unions; server-side Zod validation is unaffected and rejects nothing today. The 400 is dialect-level: the client's schema rendering converts const to enum, and Google rejects non-string enum values. I did not observe the conversion stage directly — the error paths line up exactly with the advertised const locations above.

Expected behavior / suggestion

Like the #2832 treatment, the advertised projection could present boolean literals as their declared type (keeping default where present) instead of const, e.g. { "type": "boolean", "default": false }. Canonical validation stays unchanged, and whichever projection is used (full or compact) would then survive every supported dialect.

Impact / frequency

Always (100%) for Gemini-backed clients on the Google AI API; catalog-wide, not tool-specific. Current workaround is disabling REA for those sessions.

#2832 (fixed via 80de3145e), #2999, #2813, #1484. #3806 (open) addresses a different gateway case (primitive enum without type); here the non-string enum is produced from boolean const by the client's own declaration rendering.

Originally created by @carcraze on GitHub (Oct 15, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4025 ### Summary rea's advertised tool input schemas emit non-string `const` values (booleans) on 5 tools. Clients that render declarations through the Vercel AI SDK serialize those as `enum: [false]` / `enum: [true]`, and Google's `functionDeclarations[].parameters` accepts only string enum values — so the entire request fails with HTTP 400 while REA is connected. Every Gemini model in the client becomes unusable; other providers on the same client work fine. This is the same whole-catalog failure shape as #2832 (dependentRequired, fixed in 6.5.0), #2999, #2813, #1484: one offending advertisement takes down all tools, not just the offending one. ### Environment | | | |---|---| | rea-agents | `6.4.0` (observed failure); same constructs verified in `6.5.0` advertised `tools/list` | | Node | `v24.21.0` | | Client | opencode `1.18.32`, Google Gemini provider (every Gemini model fails) | | Transport | MCP stdio, `npx -y rea-agents@<version> mcp` | ### Observed error ``` Invalid value at 'tools[0].function_declarations[112].parameters.properties[3].value.any_of[0].enum[0]' (TYPE_STRING), false Invalid value at 'tools[0].function_declarations[112].parameters.properties[3].value.any_of[1].enum[0]' (TYPE_STRING), true ``` - 100% reproducible while REA is connected; the same request is accepted as soon as REA is removed from the session. - The named property is a boolean `anyOf` (4th property of declaration 112). The shape matches `inspect_electron_page.inputSchema.properties.include_script_sources` (`anyOf[0].const = false`, `anyOf[1].const = true`). The declaration index depends on the full catalog, so I mark the exact declaration as consistent-with, not proven. ### Where the values are advertised (observed) Method: MCP stdio handshake (`initialize` → `notifications/initialized` → `tools/list`), then a recursive walk of every `inputSchema` collecting `const`/`enum` values that are not strings. No non-string `enum` was found — only boolean `const`. `rea-agents@6.5.0` — 207 tools, 5 with non-string `const`, 38 occurrences: | tool | consts | representative paths | |---|---|---| | `inspect_electron_page` | 4 | `properties.include_script_sources.anyOf[0/1]`, `$defs.__schema0/__schema4.properties.include_script_sources` | | `inspect_web_page` | 2 | `$defs.__schema11` (`false`), `$defs.__schema13` (`true`), referenced from `include_script_sources.anyOf` | | `analyze_web_bundle` | 1 | `$defs.__schema10.const = true` | | `compare_web_captures` | 30 | `before/after.inspection.scripts…source.oneOf[*].properties.included`, `…network.prior_activity_available`, `…metadata.headers_allowlisted`, `…storage.values_redacted`, `…completeness.oneOf[*].properties.equality_eligible` | | `evaluate_reconstruction_coverage` | 1 | `properties.coverage.properties.verifier_contracts.items.properties.normalization_removes_dimensions.const = false` | `rea-agents@6.4.0` — 170 tools, the same 5 tools, 17 occurrences (same constraints, referenced via `$defs` instead of inlined where noted above). `REA_MCP_INPUT_SCHEMA_PROFILE=compact` does not fully avoid it: the inline projection keeps `const`; the boolean values disappear only where the shallow reduction applies (observed on 6.5.0 — small schemas such as `inspect_electron_page` still advertise the `anyOf`-of-`const` form). Happy to paste the ~60-line scan script in a comment if it helps. ### Why the whole catalog fails Source-derived: these `const`s originate from canonical Zod literals (`z.literal(false)` / `z.literal(true)`) in discriminated unions; server-side Zod validation is unaffected and rejects nothing today. The 400 is dialect-level: the client's schema rendering converts `const` to `enum`, and Google rejects non-string enum values. I did not observe the conversion stage directly — the error paths line up exactly with the advertised `const` locations above. ### Expected behavior / suggestion Like the #2832 treatment, the advertised projection could present boolean literals as their declared `type` (keeping `default` where present) instead of `const`, e.g. `{ "type": "boolean", "default": false }`. Canonical validation stays unchanged, and whichever projection is used (full or compact) would then survive every supported dialect. ### Impact / frequency Always (100%) for Gemini-backed clients on the Google AI API; catalog-wide, not tool-specific. Current workaround is disabling REA for those sessions. ### Related #2832 (fixed via `80de3145e`), #2999, #2813, #1484. #3806 (open) addresses a different gateway case (primitive `enum` without `type`); here the non-string `enum` is produced from boolean `const` by the client's own declaration rendering.
Author
Owner

@XinwangTao commented on GitHub (Oct 15, 2026):

Good catch — this is the same whole-catalog failure shape as #2832/#2999/#2813/#1484. Non-string const values in advertised input schemas make Gemini clients reject every tool with HTTP 400, while other providers work fine. Suggest emitting boolean fields as type: boolean (or string enum values) when serializing schemas, so a single offending declaration cannot take down the whole tool catalog.

<!-- gh-comment-id:6187318084 --> @XinwangTao commented on GitHub (Oct 15, 2026): Good catch — this is the same whole-catalog failure shape as #2832/#2999/#2813/#1484. Non-string const values in advertised input schemas make Gemini clients reject every tool with HTTP 400, while other providers work fine. Suggest emitting boolean fields as `type: boolean` (or string enum values) when serializing schemas, so a single offending declaration cannot take down the whole tool catalog.
Author
Owner

@yankikucuk commented on GitHub (Oct 15, 2026):

Working on this. Reproduced on main (c61c108b5) through a real stdio tools/list scan: 38 boolean const values across 5 tools in the full profile and 5 in the compact profile, matching the table above. The fix presents boolean literals as typed boolean fields in the advertised input projection (canonical Zod validation unchanged) and adds a catalog-wide test that rejects any non-string const or enum in either profile. Draft PR follows shortly.

<!-- gh-comment-id:6189283088 --> @yankikucuk commented on GitHub (Oct 15, 2026): Working on this. Reproduced on main (c61c108b5) through a real stdio `tools/list` scan: 38 boolean `const` values across 5 tools in the full profile and 5 in the compact profile, matching the table above. The fix presents boolean literals as typed `boolean` fields in the advertised input projection (canonical Zod validation unchanged) and adds a catalog-wide test that rejects any non-string `const` or `enum` in either profile. Draft PR follows shortly.
Author
Owner

@morluto commented on GitHub (Oct 15, 2026):

Integrated on main in a2e30168a after addressing the review findings at the schema-presentation owner. Canonical parsing remains unchanged. Boolean-literal widening propagates through schema positions; affected negation/conditional groups are relaxed together, and widened oneOf becomes anyOf while retaining branch properties. Literal annotation payloads remain data.

The real @ai-sdk/google@3.0.73 request serializer produced36 non-string enums from the saved baseline full catalog and5 from compact; fixed catalogs produce0 in both. Compact baseline uses the unchanged production compact projection on the saved SDK catalog. Installed GeminiCLI0.29.5 loopback chat passed full and compact profiles, checking207 outgoing schemas and238 canonical examples each. Full/compact SDK and Ajv inclusion regressions passed, and all36 main CI jobs passed: https://github.com/morluto/rea/actions/runs/38792163880. Live Google API and OpenCode cloud execution remain unverified. Closing as addressed.

<!-- gh-comment-id:6200539223 --> @morluto commented on GitHub (Oct 15, 2026): Integrated on main in a2e30168a after addressing the review findings at the schema-presentation owner. Canonical parsing remains unchanged. Boolean-literal widening propagates through schema positions; affected negation/conditional groups are relaxed together, and widened oneOf becomes anyOf while retaining branch properties. Literal annotation payloads remain data. The real @ai-sdk/google@3.0.73 request serializer produced36 non-string enums from the saved baseline full catalog and5 from compact; fixed catalogs produce0 in both. Compact baseline uses the unchanged production compact projection on the saved SDK catalog. Installed GeminiCLI0.29.5 loopback chat passed full and compact profiles, checking207 outgoing schemas and238 canonical examples each. Full/compact SDK and Ajv inclusion regressions passed, and all36 main CI jobs passed: https://github.com/morluto/rea/actions/runs/38792163880. Live Google API and OpenCode cloud execution remain unverified. Closing as addressed.
Author
Owner

@taylorazulai commented on GitHub (Oct 16, 2026):

Requesting a patch release (6.5.1) containing the fix from a2e30168a.

As of 2026-10-16, npm latest is still rea-agents@6.5.0 and the GitHub release list shows no release after the fix landed on main (2026-10-15). The published 6.5.0 package still ships the broken schemas: an independent stdio tools/list scan of npx -y rea-agents@6.5.0 mcp today found the same 38 boolean const occurrences across the same 5 tools (inspect_electron_page, inspect_web_page, analyze_web_bundle, compare_web_captures, evaluate_reconstruction_coverage).

Impact in the wild: OpenCode with a Gemini-backed provider (EdenAI google/gemini-3.8-flash, MCP stdio via npx -y rea-agents@6.5.0 mcp) fails every request with the whole-catalog HTTP 400 (Invalid value at 'tools[0].function_declarations[...].enum[0]' (TYPE_STRING), false/true) while REA is connected, making every Gemini model in the client unusable — not just the 5 offending tools. REA_MCP_INPUT_SCHEMA_PROFILE=compact does not help, since the compact profile also contained non-string consts pre-fix (per the reproduction above).

Since the fix and its catalog-wide regression test are already on main, cutting a patch release would unblock Gemini users without any further code changes. Users on 6.5.0 currently have to either disable the 5 tools client-side or avoid Gemini models entirely.

<!-- gh-comment-id:6214275471 --> @taylorazulai commented on GitHub (Oct 16, 2026): Requesting a patch release (6.5.1) containing the fix from a2e30168a. As of 2026-10-16, npm `latest` is still `rea-agents@6.5.0` and the GitHub release list shows no release after the fix landed on main (2026-10-15). The published 6.5.0 package still ships the broken schemas: an independent stdio `tools/list` scan of `npx -y rea-agents@6.5.0 mcp` today found the same 38 boolean `const` occurrences across the same 5 tools (`inspect_electron_page`, `inspect_web_page`, `analyze_web_bundle`, `compare_web_captures`, `evaluate_reconstruction_coverage`). Impact in the wild: OpenCode with a Gemini-backed provider (EdenAI `google/gemini-3.8-flash`, MCP stdio via `npx -y rea-agents@6.5.0 mcp`) fails every request with the whole-catalog HTTP 400 (`Invalid value at 'tools[0].function_declarations[...].enum[0]' (TYPE_STRING), false/true`) while REA is connected, making every Gemini model in the client unusable — not just the 5 offending tools. `REA_MCP_INPUT_SCHEMA_PROFILE=compact` does not help, since the compact profile also contained non-string consts pre-fix (per the reproduction above). Since the fix and its catalog-wide regression test are already on main, cutting a patch release would unblock Gemini users without any further code changes. Users on 6.5.0 currently have to either disable the 5 tools client-side or avoid Gemini models entirely.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#1601
No description provided.