[GH-ISSUE #4620] [Bug] Gemini CLI throws error 400 'INVALID_ARGUMENT' when using REA skill #2403

Closed
opened 2026-10-17 21:04:12 +00:00 by bsakaguchi · 21 comments
Owner

Originally created by @ElektroStudios on GitHub (Oct 16, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/4620

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

MCP or agent integration

Observed behavior

I recently installed REA (Reverse Engineer Anything) alongside its bundled skill file, configured Gemini CLI in REA interface, and ran the following prompt in Gemini CLI:

Use REA to analyze the native binary at C:/_gemini/ReNamer.exe. Your goal is to help me hardcode a dark theme. I need you to look up the import address table (IAT) and locate all references to Win32 API calls related to color drawing: GetSysColor, SetBkColor, SetTextColor, or CreateSolidBrush. Return the pseudocode or assembly of the functions that prepare the graphical user interface (GUI) and give me the offsets (virtual and physical memory addresses) where the color values are passed, so I can patch them with a hex editor. Please execute actions one by one, do not run tools in parallel.

Sorry if I can't provide much useful data; this is my first time using Gemini CLI (and my first experience using a CLI AI agent), which I installed specifically to use REA, and I ran straight into this issue.

Reproduction

Steps to Reproduce

  1. Install REA globally via npm:
    npm install --global rea-agents
    
  2. Run the setup assistant and configure REA for Gemini CLI:
    npx rea-agents setup
    
    (Select Gemini CLI and confirm installing the bundled reverse-engineering skill)
  3. Launch Gemini CLI with a valid API key:
    gemini
    
  4. Navigate to the directory containing the target binary (e.g., C:/_gemini/ReNamer.exe).
  5. Send the following prompt:
    Use REA to analyze the native binary at C:/_gemini/ReNamer.exe. Your goal is to help me hardcode a dark theme. I need you to look up the import address table (IAT) and locate all references to Win32 API calls related to color drawing: GetSysColor, SetBkColor, SetTextColor, or CreateSolidBrush. Return the pseudocode or assembly of the functions that prepare the graphical user interface (GUI) and give me the offsets (virtual and physical memory addresses) where the color values are passed, so I can patch them with a hex editor. Please execute actions one by one, do not run tools in parallel.
    

Expected behavior

I expected Gemini CLI to successfully load REA's MCP server, parse the registered tool definitions, and process my prompts normally without triggering API errors, allowing the agent to execute binary analysis workflows using the provided toolset.

Impact and scope

Frequency: always.

REA version

6.5.0

Runtime and platform

Node 24.16.0; Windows 10.0.19045.5371 x64; Ghidra 12.1.4

Target and artifact context

PE 32-bit (x86) Native Windows Executable, Standard desktop GUI application (compiled in Delphi, utilizing the VCL framework)

Interface

CLI

Earliest failure stage

Unknown

Relevant output or evidence

Error 400 'INVALID_ARGUMENT' (from Gemini CLI)

Image

Typed outcome or recovery expected

No response

Analysis or suspected cause

Here is what the Gemini web interface told me when I brought up this issue about the REA skill file (might be useful):

When Gemini CLI starts up and loads REA's MCP server, it tries to inject the JSON schema of those 207 reverse engineering tools into the system prompt (the Function Calling schema). The Gemini API has strict limits on complexity, nesting depth, and the maximum number of tools it can receive in a single request. By dumping 207 complex tools all at once, Google's parser collapses, treats it as a malformed payload, and spits out a 400 Bad Request before even reading your question.

You won't be able to fix this by editing that text file, because the issue lies in the sheer number of functions that the MCP server binary spits out to the API.

Additional context

No response

Originally created by @ElektroStudios on GitHub (Oct 16, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4620 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area MCP or agent integration ### Observed behavior I recently installed [REA](https://github.com/morluto/rea) (Reverse Engineer Anything) alongside its bundled skill file, configured Gemini CLI in REA interface, and ran the following prompt in Gemini CLI: `Use REA to analyze the native binary at C:/_gemini/ReNamer.exe. Your goal is to help me hardcode a dark theme. I need you to look up the import address table (IAT) and locate all references to Win32 API calls related to color drawing: GetSysColor, SetBkColor, SetTextColor, or CreateSolidBrush. Return the pseudocode or assembly of the functions that prepare the graphical user interface (GUI) and give me the offsets (virtual and physical memory addresses) where the color values are passed, so I can patch them with a hex editor. Please execute actions one by one, do not run tools in parallel.` Sorry if I can't provide much useful data; this is my first time using Gemini CLI (and my first experience using a CLI AI agent), which I installed specifically to use REA, and I ran straight into this issue. ### Reproduction ### Steps to Reproduce 1. Install [REA](https://github.com/morluto/rea) globally via npm: ```bash npm install --global rea-agents ``` 2. Run the setup assistant and configure REA for Gemini CLI: ```bash npx rea-agents setup ``` *(Select Gemini CLI and confirm installing the bundled reverse-engineering skill)* 3. Launch Gemini CLI with a valid API key: ```bash gemini ``` 4. Navigate to the directory containing the target binary (e.g., `C:/_gemini/ReNamer.exe`). 5. Send the following prompt: ```text Use REA to analyze the native binary at C:/_gemini/ReNamer.exe. Your goal is to help me hardcode a dark theme. I need you to look up the import address table (IAT) and locate all references to Win32 API calls related to color drawing: GetSysColor, SetBkColor, SetTextColor, or CreateSolidBrush. Return the pseudocode or assembly of the functions that prepare the graphical user interface (GUI) and give me the offsets (virtual and physical memory addresses) where the color values are passed, so I can patch them with a hex editor. Please execute actions one by one, do not run tools in parallel. ``` ### Expected behavior I expected Gemini CLI to successfully load REA's MCP server, parse the registered tool definitions, and process my prompts normally without triggering API errors, allowing the agent to execute binary analysis workflows using the provided toolset. ### Impact and scope Frequency: always. ### REA version 6.5.0 ### Runtime and platform Node 24.16.0; Windows 10.0.19045.5371 x64; Ghidra 12.1.4 ### Target and artifact context PE 32-bit (x86) Native Windows Executable, Standard desktop GUI application (compiled in Delphi, utilizing the VCL framework) ### Interface CLI ### Earliest failure stage Unknown ### Relevant output or evidence Error 400 'INVALID_ARGUMENT' (from Gemini CLI) <img width="1920" height="487" alt="Image" src="https://github.com/user-attachments/assets/82dcb521-115f-4171-a182-dcd2b4ee369e" /> ### Typed outcome or recovery expected _No response_ ### Analysis or suspected cause Here is what the Gemini web interface told me when I brought up this issue about the REA skill file (might be useful): > When Gemini CLI starts up and loads REA's MCP server, it tries to inject the JSON schema of those 207 reverse engineering tools into the system prompt (the Function Calling schema). The Gemini API has strict limits on complexity, nesting depth, and the maximum number of tools it can receive in a single request. By dumping 207 complex tools all at once, Google's parser collapses, treats it as a malformed payload, and spits out a 400 Bad Request before even reading your question. > > You won't be able to fix this by editing that text file, because the issue lies in the sheer number of functions that the MCP server binary spits out to the API. ### Additional context _No response_
Author
Owner

@Nitin13-git commented on GitHub (Oct 16, 2026):

Thanks for the report. This looks like it may be the same problem as #4025 (closed): on rea-agents@6.5.0, five tools advertise boolean const values (false/true), and Gemini rejects those in function declarations (TYPE_STRING expected). The fix is a2e30168a on main, but it is not in a published release yet (npm latest is still 6.5.0), so a fresh npm install of 6.5.0 still has the broken schemas.

From a stdio tools/list scan of current main (207 tools): no non-string const or enum, no $ref/$defs, and no dependentRequired/dependencies. I have not run Gemini CLI, so I can't confirm that this removes your 400.

To find out whether it is the same problem or something new, could you paste the full error text from Gemini CLI (not only 400 INVALID_ARGUMENT)? In #4025 the message named the exact path, for example tools[0].function_declarations[112].parameters.properties[3]..., which identifies the field. Please also include the Gemini CLI version (gemini --version). Redact any key or private path.

<!-- gh-comment-id:6226974538 --> @Nitin13-git commented on GitHub (Oct 16, 2026): Thanks for the report. This looks like it may be the same problem as #4025 (closed): on `rea-agents@6.5.0`, five tools advertise boolean `const` values (`false`/`true`), and Gemini rejects those in function declarations (`TYPE_STRING` expected). The fix is `a2e30168a` on `main`, but it is not in a published release yet (npm `latest` is still 6.5.0), so a fresh `npm install` of 6.5.0 still has the broken schemas. From a stdio `tools/list` scan of current `main` (207 tools): no non-string `const` or `enum`, no `$ref`/`$defs`, and no `dependentRequired`/`dependencies`. I have not run Gemini CLI, so I can't confirm that this removes your 400. To find out whether it is the same problem or something new, could you paste the full error text from Gemini CLI (not only `400 INVALID_ARGUMENT`)? In #4025 the message named the exact path, for example `tools[0].function_declarations[112].parameters.properties[3]...`, which identifies the field. Please also include the Gemini CLI version (`gemini --version`). Redact any key or private path.
Author
Owner

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

This matches the same root area as #4025: Gemini's API is strict about tool schemas, and once a single malformed schema is present in the 207-tool catalog it can reject the whole request with 400 INVALID_ARGUMENT before any tool call happens. The described error (constant values of non-string type in enum/const fields) is the kind of thing that breaks Gemini's parser at catalog load time, so I'd treat #4025 as the primary fix and this as the user-facing symptom. Beyond the schema fix, a reasonable mitigation is to reduce the catalog surface for providers with tight limits — e.g., only advertise tools after a minimal "what can you do" probe, or group related tools so the initial request carries fewer definitions. ElektroStudios' report is very useful because it documents the exact CLI flow and the impact of the catalog size; having a repro like this will make it much easier to verify the fix actually unblocks Gemini users.

<!-- gh-comment-id:6227990123 --> @XinwangTao commented on GitHub (Oct 17, 2026): This matches the same root area as #4025: Gemini's API is strict about tool schemas, and once a single malformed schema is present in the 207-tool catalog it can reject the whole request with 400 INVALID_ARGUMENT before any tool call happens. The described error (constant values of non-string type in enum/const fields) is the kind of thing that breaks Gemini's parser at catalog load time, so I'd treat #4025 as the primary fix and this as the user-facing symptom. Beyond the schema fix, a reasonable mitigation is to reduce the catalog surface for providers with tight limits — e.g., only advertise tools after a minimal "what can you do" probe, or group related tools so the initial request carries fewer definitions. ElektroStudios' report is very useful because it documents the exact CLI flow and the impact of the catalog size; having a repro like this will make it much easier to verify the fix actually unblocks Gemini users.
Author
Owner

@ElektroStudios commented on GitHub (Oct 17, 2026):

    To find out whether it is the same problem or something new, could you paste the full error text from Gemini CLI (not only `400 INVALID_ARGUMENT`)? In [#4025](https://github.com/morluto/rea/issues/4025) the message named the exact path, for example `tools[0].function_declarations[112].parameters.properties[3]...`, which identifies the field. Please also include the Gemini CLI version (`gemini --version`). Redact any key or private path.

First of all, thank you very much for your support and for looking into this!

Here is the requested information. My Gemini CLI version is: 0.64.0

Client Information
> /about
│ CLI Version                                                                       0.64.0                                                                                                                                                  │
│ Git Commit                                                                        4a0749ace                                                                                                                                               │
│ Model                                                                             gemini-3.1-pro-preview                                                                                                                                  │
│ Sandbox                                                                           no sandbox                                                                                                                                              │
│ OS                                                                                win32                                                                                                                                                   │
│ Auth Method                                                                       gemini-api-key

Regarding the exact error path (tools[0]...), I am unable to provide it because the Gemini CLI does not output the details or fieldViolations array, even with "Error Verbosity" set to full in its settings.

This is the absolute maximum output the CLI provides when the 400 error occurs:

✕ [API Error: {"error":{"message":"{\n  \"error\": {\n    \"code\": 400,\n    \"message\": \"Request contains an invalid argument.\",\n    \"status\": \"INVALID_ARGUMENT\"\n  }\n}\n","code":400,"status":"Bad Request"}}]

Just to isolate the issue: if I disable the REA skill, Gemini CLI works without problems. This may confirm that the error is exclusively triggered by the REA tool schema and is not a general configuration issue on my end.

Let me know if there is a debug flag or environment variable I can use to intercept the raw HTTP response to get that exact path for you.

<!-- gh-comment-id:6228646399 --> @ElektroStudios commented on GitHub (Oct 17, 2026): > To find out whether it is the same problem or something new, could you paste the full error text from Gemini CLI (not only `400 INVALID_ARGUMENT`)? In [#4025](https://github.com/morluto/rea/issues/4025) the message named the exact path, for example `tools[0].function_declarations[112].parameters.properties[3]...`, which identifies the field. Please also include the Gemini CLI version (`gemini --version`). Redact any key or private path. First of all, thank you very much for your support and for looking into this! Here is the requested information. My Gemini CLI version is: **0.64.0** <details> <summary>Client Information</summary> ```console > /about │ CLI Version 0.64.0 │ │ Git Commit 4a0749ace │ │ Model gemini-3.1-pro-preview │ │ Sandbox no sandbox │ │ OS win32 │ │ Auth Method gemini-api-key ``` </details> -------------- Regarding the exact error path (`tools[0]...`), I am unable to provide it because the Gemini CLI does not output the `details` or `fieldViolations` array, even with "Error Verbosity" set to `full` in its settings. This is the absolute maximum output the CLI provides when the 400 error occurs: ```json ✕ [API Error: {"error":{"message":"{\n \"error\": {\n \"code\": 400,\n \"message\": \"Request contains an invalid argument.\",\n \"status\": \"INVALID_ARGUMENT\"\n }\n}\n","code":400,"status":"Bad Request"}}] ``` Just to isolate the issue: if I disable the REA skill, Gemini CLI works without problems. This may confirm that the error is exclusively triggered by the REA tool schema and is not a general configuration issue on my end. Let me know if there is a debug flag or environment variable I can use to intercept the raw HTTP response to get that exact path for you.
Author
Owner

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

Thanks for the extra data. The fact that Gemini CLI works fine with the REA skill disabled is strong confirmation that the failure is triggered purely by REA's tool catalog, which aligns with the #4025 root cause — the boolean const schemas fixed on main (a2e30168a) but not yet released.

On capturing the exact field path: Gemini CLI does not surface fieldViolations, but you can intercept the raw request before it leaves the machine by running it behind an HTTPS inspection proxy (mitmproxy, HTTP Toolkit, or Fiddler on Windows) with a trusted root cert, then reading the JSON body of the POST to generativelanguage.googleapis.com — the offending field will be listed there. Also worth checking: some Gemini CLI builds support a debug log flag (gemini --help → logging options), which may print the request payload at debug level.

Since npm latest is still 6.5.0, the fastest way to verify the fix is to retest this exact flow once a release containing a2e30168a ships. If the 400 persists after that, the catalog-size mitigation (advertising tools in smaller groups) becomes the likely next step.

<!-- gh-comment-id:6229474301 --> @XinwangTao commented on GitHub (Oct 17, 2026): Thanks for the extra data. The fact that Gemini CLI works fine with the REA skill disabled is strong confirmation that the failure is triggered purely by REA's tool catalog, which aligns with the #4025 root cause — the boolean const schemas fixed on main (a2e30168a) but not yet released. On capturing the exact field path: Gemini CLI does not surface fieldViolations, but you can intercept the raw request before it leaves the machine by running it behind an HTTPS inspection proxy (mitmproxy, HTTP Toolkit, or Fiddler on Windows) with a trusted root cert, then reading the JSON body of the POST to generativelanguage.googleapis.com — the offending field will be listed there. Also worth checking: some Gemini CLI builds support a debug log flag (gemini --help → logging options), which may print the request payload at debug level. Since npm latest is still 6.5.0, the fastest way to verify the fix is to retest this exact flow once a release containing a2e30168a ships. If the 400 persists after that, the catalog-size mitigation (advertising tools in smaller groups) becomes the likely next step.
Author
Owner

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

@ElektroStudios A couple of concrete ways to get the exact field without waiting for CLI diagnostics:

  1. Proxy capture: run mitmproxy (or Fiddler/Charles) on 127.0.0.1:8080, set HTTPS_PROXY=http://127.0.0.1:8080 before launching gemini, install the mitmproxy CA cert, and the failing POST to generativelanguage.googleapis.com will expose the full function_declarations array. That gives Nitin13-git the exact tools[...].function_declarations[...] path even though the CLI hides fieldViolations.

  2. Faster than that: verify the fix right now. The #4025 fix (a2e30168a) is on main but not in the published 6.5.0, so clone the repo, npm ci && npm run build, and point the REA MCP server at that build. If the 400 disappears, this is confirmed as the same root cause; if it persists, the capture from step 1 will pinpoint which schema still breaks Gemini.

Your observation that disabling the REA skill makes Gemini CLI work is already strong evidence the 400 originates from the tool catalog itself rather than your config, so narrowing it to the specific schema is mostly about closing the loop for the maintainers.

<!-- gh-comment-id:6229477078 --> @XinwangTao commented on GitHub (Oct 17, 2026): @ElektroStudios A couple of concrete ways to get the exact field without waiting for CLI diagnostics: 1. Proxy capture: run mitmproxy (or Fiddler/Charles) on 127.0.0.1:8080, set `HTTPS_PROXY=http://127.0.0.1:8080` before launching `gemini`, install the mitmproxy CA cert, and the failing POST to generativelanguage.googleapis.com will expose the full function_declarations array. That gives Nitin13-git the exact `tools[...].function_declarations[...]` path even though the CLI hides fieldViolations. 2. Faster than that: verify the fix right now. The #4025 fix (a2e30168a) is on main but not in the published 6.5.0, so clone the repo, `npm ci && npm run build`, and point the REA MCP server at that build. If the 400 disappears, this is confirmed as the same root cause; if it persists, the capture from step 1 will pinpoint which schema still breaks Gemini. Your observation that disabling the REA skill makes Gemini CLI work is already strong evidence the 400 originates from the tool catalog itself rather than your config, so narrowing it to the specific schema is mostly about closing the loop for the maintainers.
Author
Owner

@ElektroStudios commented on GitHub (Oct 17, 2026):

@ElektroStudios A couple of concrete ways to get the exact field without waiting for CLI diagnostics:

2. Faster than that: verify the fix right now. The [[Bug] Gemini-backed clients reject the whole tool catalog: advertised schemas emit non-string const values (boolean enum MUST be TYPE_STRING) #4025](https://github.com/morluto/rea/issues/4025) fix ([a2e3016](https://github.com/morluto/rea/commit/a2e30168a046f3b79319eb7fbaf807b802104199)) is on main but not in the published 6.5.0, so clone the repo, `npm ci && npm run build`, and point the REA MCP server at that build. If the 400 disappears, this is confirmed as the same root cause; if it persists, the capture from step 1 will pinpoint which schema still breaks Gemini.

I went ahead and tested step 2. (To be completely honest, I am not a Node/npm guy, so I used Google Gemini to help me navigate the whole cloning process, bypass the missing Windows binaries by extracting .node and manifest.json from the official 6.5.0 tarball, and handle the build/link).

After doing all that: I cloned the main branch, successfully bypassed the build errors, ran npm run build:cached, and linked it globally (npm link). Then, I re-ran rea setup to ensure Gemini CLI hooked into this local patched build. (I verified via PowerShell's Get-Item "$env:APPDATA\npm\node_modules\rea-agents" | Select-Object LinkType, Target that the global rea-agents node_module is physically a Junction symlink pointing directly to my local cloned repository, not a cached global install—which I uninstalled beforehand just to be 100% sure).

Unfortunately, the result is exactly the same. The 400 Bad Request (INVALID_ARGUMENT) error still persists the moment the prompt is sent.

It seems the a2e3016 fix for boolean const schemas is not enough. The Gemini API is still flat-out rejecting the payload, which strongly may point to the depth and complexity of injecting 207 tools into the function calling schema all at once.

As you mentioned, it looks like the catalog-size mitigation (advertising tools in smaller groups or lazy-loading them) is definitely the necessary next step. Let me know if you need me to test that implementation once it's drafted!

I also tried your Step 1 to get the exact fieldViolations path for you (using the cloned local repo with your fix). Gemini walked me through the process, but I hit a wall with the tooling itself:

  1. Fiddler proxying fails / does not capture the related CLI traffic (it works fine for processes such as firefox.exe). Maybe I did something wrong or maybe the Gemini CLI's internal fetch seems to completely ignore standard HTTPS_PROXY environment variables.

  2. Even when checking the raw gemini-client-error-*.json debug files dumped by the Gemini CLI with the --debug flag and error verbosity = full, the deep API response is truncated. It only logs the generic Request contains an invalid argument string and completely omits the fieldViolations array:

{
  "error": {
    "message": "{\"error\":{\"message\":\"{\\n  \\\"error\\\": {\\n    \\\"code\\\": 400,\\n    \\\"message\\\": \\\"Request contains an invalid argument.\\\",\\n    \\\"status\\\": \\\"INVALID_ARGUMENT\\\"\\n  }\\n}\\n\",\"code\":400,\"status\":\"Bad Request\"}}",
    "stack": "ApiError: {\"error\":{\"message\":\"{\\n  \\\"error\\\": {\\n    \\\"code\\\": 400,\\n    \\\"message\\\": \\\"Request contains an invalid argument.\\\",\\n    \\\"status\\\": \\\"INVALID_ARGUMENT\\\"\\n  }\\n}\\n\",\"code\":400,\"status\":\"Bad Request\"}}\n    at throwErrorIfNotOK (file:///C:/Users/Administrador/AppData/Roaming/npm/node_modules/@google/gemini-cli/bundle/chunk-NR7L3FXV.js:267903:24)\n    at process.processTicksAndRejections (node:internal/process/task_queues:104:5)\n    at async file:///C:/Users/Administrador/AppData/Roaming/npm/node_modules/@google/gemini-cli/bundle/chunk-NR7L3FXV.js:267666:7\n    at async Models.generateContentStream (file:///C:/Users/Administrador/AppData/Roaming/npm/node_modules/@google/gemini-cli/bundle/chunk-NR7L3FXV.js:268762:16)\n    at async file:///C:/Users/Administrador/AppData/Roaming/npm/node_modules/@google/gemini-cli/bundle/chunk-NR7L3FXV.js:312364:19\n    at async file:///C:/Users/Administrador/AppData/Roaming/npm/node_modules/@google/gemini-cli/bundle/chunk-NR7L3FXV.js:288670:23\n    at async retryWithBackoff (file:///C:/Users/Administrador/AppData/Roaming/npm/node_modules/@google/gemini-cli/bundle/chunk-NR7L3FXV.js:308754:23)\n    at async GeminiChat.makeApiCallAndProcessStream (file:///C:/Users/Administrador/AppData/Roaming/npm/node_modules/@google/gemini-cli/bundle/chunk-NR7L3FXV.js:333648:28)\n    at async GeminiChat.streamWithRetries (file:///C:/Users/Administrador/AppData/Roaming/npm/node_modules/@google/gemini-cli/bundle/chunk-NR7L3FXV.js:333343:29)\n    at async Turn.run (file:///C:/Users/Administrador/AppData/Roaming/npm/node_modules/@google/gemini-cli/bundle/chunk-NR7L3FXV.js:334387:24)"
  },
  "context": [
    {
      "role": "user",
      "parts": [
        {
          "text": "<session_context>\nThis is the Gemini CLI. We are setting up the context for our chat.\nToday's date is sábado, 17 de octubre de 2026 (formatted according to the user's locale).\nMy operating system is: win32\nThe project's temporary directory is: C:\\Users\\Administrador\\.gemini\\tmp\\gemini\n- **Workspace Directories:**\n  - C:\\_gemini\n- **Directory Structure:**\n\nShowing up to 200 items (files + folders).\n\nC:\\_gemini\\\n├───Migration.log\n├───ReNamer.exe\n├───Settings.ini\n└───Presets\\\n    └───[default].rnp\n\n\n</session_context>"
        }
      ]
    },
    {
      "role": "user",
      "parts": [
        {
          "text": "Use REA to analyze the native binary at C:/_gemini/ReNamer.exe. Your goal is to help me hardcode a dark theme. I need you to look up the import address table (IAT) and locate all references to Win32 API calls related to color drawing: GetSysColor, SetBkColor, SetTextColor, or CreateSolidBrush. Return the pseudocode or assembly of the functions that prepare the graphical user interface (GUI) and give me the offsets (virtual and physical memory addresses) where the color values are passed, so I can patch them with a hex editor. Please execute actions one by one, do not run tools in parallel."
        }
      ]
    }
  ]
}
<!-- gh-comment-id:6236832791 --> @ElektroStudios commented on GitHub (Oct 17, 2026): > [@ElektroStudios](https://github.com/ElektroStudios) A couple of concrete ways to get the exact field without waiting for CLI diagnostics: > 2. Faster than that: verify the fix right now. The [[Bug] Gemini-backed clients reject the whole tool catalog: advertised schemas emit non-string const values (boolean enum MUST be TYPE_STRING) #4025](https://github.com/morluto/rea/issues/4025) fix ([a2e3016](https://github.com/morluto/rea/commit/a2e30168a046f3b79319eb7fbaf807b802104199)) is on main but not in the published 6.5.0, so clone the repo, `npm ci && npm run build`, and point the REA MCP server at that build. If the 400 disappears, this is confirmed as the same root cause; if it persists, the capture from step 1 will pinpoint which schema still breaks Gemini. I went ahead and tested step 2. (To be completely honest, I am not a Node/npm guy, so I used Google Gemini to help me navigate the whole cloning process, bypass the missing Windows binaries by extracting `.node` and `manifest.json` from the official 6.5.0 tarball, and handle the build/link). After doing all that: I cloned the `main` branch, successfully bypassed the build errors, ran `npm run build:cached`, and linked it globally (`npm link`). Then, I re-ran `rea setup` to ensure Gemini CLI hooked into this local patched build. (I verified via PowerShell's `Get-Item "$env:APPDATA\npm\node_modules\rea-agents" | Select-Object LinkType, Target` that the global `rea-agents` node_module is physically a Junction symlink pointing directly to my local cloned repository, not a cached global install—which I uninstalled beforehand just to be 100% sure). Unfortunately, the result is exactly the same. The `400 Bad Request (INVALID_ARGUMENT)` error still persists the moment the prompt is sent. It seems the `a2e3016` fix for boolean const schemas is not enough. The Gemini API is still flat-out rejecting the payload, which strongly may point to the depth and complexity of injecting 207 tools into the function calling schema all at once. As you mentioned, it looks like the catalog-size mitigation (advertising tools in smaller groups or lazy-loading them) is definitely the necessary next step. Let me know if you need me to test that implementation once it's drafted! I also tried your Step 1 to get the exact fieldViolations path for you (using the cloned local repo with your fix). Gemini walked me through the process, but I hit a wall with the tooling itself: 1. Fiddler proxying fails / does not capture the related CLI traffic (it works fine for processes such as firefox.exe). Maybe I did something wrong or maybe the Gemini CLI's internal fetch seems to completely ignore standard HTTPS_PROXY environment variables. 2. Even when checking the raw `gemini-client-error-*.json` debug files dumped by the Gemini CLI with the `--debug` flag and error verbosity = `full`, the deep API response is truncated. It only logs the generic `Request contains an invalid argument` string and completely omits the `fieldViolations` array: ```json { "error": { "message": "{\"error\":{\"message\":\"{\\n \\\"error\\\": {\\n \\\"code\\\": 400,\\n \\\"message\\\": \\\"Request contains an invalid argument.\\\",\\n \\\"status\\\": \\\"INVALID_ARGUMENT\\\"\\n }\\n}\\n\",\"code\":400,\"status\":\"Bad Request\"}}", "stack": "ApiError: {\"error\":{\"message\":\"{\\n \\\"error\\\": {\\n \\\"code\\\": 400,\\n \\\"message\\\": \\\"Request contains an invalid argument.\\\",\\n \\\"status\\\": \\\"INVALID_ARGUMENT\\\"\\n }\\n}\\n\",\"code\":400,\"status\":\"Bad Request\"}}\n at throwErrorIfNotOK (file:///C:/Users/Administrador/AppData/Roaming/npm/node_modules/@google/gemini-cli/bundle/chunk-NR7L3FXV.js:267903:24)\n at process.processTicksAndRejections (node:internal/process/task_queues:104:5)\n at async file:///C:/Users/Administrador/AppData/Roaming/npm/node_modules/@google/gemini-cli/bundle/chunk-NR7L3FXV.js:267666:7\n at async Models.generateContentStream (file:///C:/Users/Administrador/AppData/Roaming/npm/node_modules/@google/gemini-cli/bundle/chunk-NR7L3FXV.js:268762:16)\n at async file:///C:/Users/Administrador/AppData/Roaming/npm/node_modules/@google/gemini-cli/bundle/chunk-NR7L3FXV.js:312364:19\n at async file:///C:/Users/Administrador/AppData/Roaming/npm/node_modules/@google/gemini-cli/bundle/chunk-NR7L3FXV.js:288670:23\n at async retryWithBackoff (file:///C:/Users/Administrador/AppData/Roaming/npm/node_modules/@google/gemini-cli/bundle/chunk-NR7L3FXV.js:308754:23)\n at async GeminiChat.makeApiCallAndProcessStream (file:///C:/Users/Administrador/AppData/Roaming/npm/node_modules/@google/gemini-cli/bundle/chunk-NR7L3FXV.js:333648:28)\n at async GeminiChat.streamWithRetries (file:///C:/Users/Administrador/AppData/Roaming/npm/node_modules/@google/gemini-cli/bundle/chunk-NR7L3FXV.js:333343:29)\n at async Turn.run (file:///C:/Users/Administrador/AppData/Roaming/npm/node_modules/@google/gemini-cli/bundle/chunk-NR7L3FXV.js:334387:24)" }, "context": [ { "role": "user", "parts": [ { "text": "<session_context>\nThis is the Gemini CLI. We are setting up the context for our chat.\nToday's date is sábado, 17 de octubre de 2026 (formatted according to the user's locale).\nMy operating system is: win32\nThe project's temporary directory is: C:\\Users\\Administrador\\.gemini\\tmp\\gemini\n- **Workspace Directories:**\n - C:\\_gemini\n- **Directory Structure:**\n\nShowing up to 200 items (files + folders).\n\nC:\\_gemini\\\n├───Migration.log\n├───ReNamer.exe\n├───Settings.ini\n└───Presets\\\n └───[default].rnp\n\n\n</session_context>" } ] }, { "role": "user", "parts": [ { "text": "Use REA to analyze the native binary at C:/_gemini/ReNamer.exe. Your goal is to help me hardcode a dark theme. I need you to look up the import address table (IAT) and locate all references to Win32 API calls related to color drawing: GetSysColor, SetBkColor, SetTextColor, or CreateSolidBrush. Return the pseudocode or assembly of the functions that prepare the graphical user interface (GUI) and give me the offsets (virtual and physical memory addresses) where the color values are passed, so I can patch them with a hex editor. Please execute actions one by one, do not run tools in parallel." } ] } ] } ```
Author
Owner

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

Thanks for the detailed repro. This confirms my earlier point that the schema-level fix (non-string const values) is the root cause, and the Gemini 400 is just the user-facing symptom. Agree that trimming the catalog surface for providers with tight schema limits is a reasonable mitigation — it also helps VS Code which rejected mcp_rea_build_call_path for the same class of schema issue. Will retest this exact Gemini flow once a release containing the fix is out.

<!-- gh-comment-id:6244039864 --> @XinwangTao commented on GitHub (Oct 18, 2026): Thanks for the detailed repro. This confirms my earlier point that the schema-level fix (non-string const values) is the root cause, and the Gemini 400 is just the user-facing symptom. Agree that trimming the catalog surface for providers with tight schema limits is a reasonable mitigation — it also helps VS Code which rejected `mcp_rea_build_call_path` for the same class of schema issue. Will retest this exact Gemini flow once a release containing the fix is out.
Author
Owner

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

Thanks for the hands-on verification — that's really valuable. The fact that the 400 still reproduces on main (with a2e3016 included) means the boolean const schema was not the only trigger; the catalog size/complexity (207 tools injected at once) now looks like the more likely cause. I agree catalog grouping / lazy-loading is the right next step.

About step 1: if Fiddler is giving you trouble, mitmproxy is a lighter alternative (pip install mitmproxy, run mitmproxy --listen-port 8080, set HTTPS_PROXY=http://127.0.0.1:8080 before launching gemini, and install the mitmproxy CA cert). Or, even simpler, patch the MCP client in Node to log the full tools/list response before it is sent, so you don't need a system proxy at all.

Once the grouped/on-demand catalog is drafted, your repro will be very useful to confirm the fix actually unblocks Gemini users. Happy to help review the implementation when it lands.

<!-- gh-comment-id:6244049020 --> @XinwangTao commented on GitHub (Oct 18, 2026): Thanks for the hands-on verification — that's really valuable. The fact that the 400 still reproduces on main (with a2e3016 included) means the boolean const schema was not the only trigger; the catalog size/complexity (207 tools injected at once) now looks like the more likely cause. I agree catalog grouping / lazy-loading is the right next step. About step 1: if Fiddler is giving you trouble, mitmproxy is a lighter alternative (pip install mitmproxy, run mitmproxy --listen-port 8080, set HTTPS_PROXY=http://127.0.0.1:8080 before launching gemini, and install the mitmproxy CA cert). Or, even simpler, patch the MCP client in Node to log the full tools/list response before it is sent, so you don't need a system proxy at all. Once the grouped/on-demand catalog is drafted, your repro will be very useful to confirm the fix actually unblocks Gemini users. Happy to help review the implementation when it lands.
Author
Owner

@ElektroStudios commented on GitHub (Oct 18, 2026):

Or, even simpler, patch the MCP client in Node to log the full tools/list response before it is sent, so you don't need a system proxy at all.

I saw your suggestions about mitmproxy and patching the Node client. To be completely honest, since I'm really not a Node guy, setting up more proxies or trying to inject JS code into the client was driving me a bit crazy. So I asked Gemini to help me find a dummy-proof way to get the exact payload for you.

The AI pointed me to what it seems a cleaner route: use the official MCP Inspector.

I just ran npx @modelcontextprotocol/inspector rea --mcp to hook directly into my local patched build. The web UI automatically requested the tools/list, and I simply clicked the 'Export' button on the messages panel to download the whole thing.

I've attached that exported zipped JSON file here:

The JSON file occupies 20 MB after extraction.

Hopefully, this raw dump is exactly what you need to see which specific schema is still choking the Google API.

<!-- gh-comment-id:6251137834 --> @ElektroStudios commented on GitHub (Oct 18, 2026): > Or, even simpler, patch the MCP client in Node to log the full tools/list response before it is sent, so you don't need a system proxy at all. I saw your suggestions about `mitmproxy` and patching the Node client. To be completely honest, since I'm really not a Node guy, setting up more proxies or trying to inject JS code into the client was driving me a bit crazy. So I asked Gemini to help me find a dummy-proof way to get the exact payload for you. The AI pointed me to what it seems a cleaner route: use the official MCP Inspector. I just ran `npx @modelcontextprotocol/inspector rea --mcp` to hook directly into my local patched build. The web UI automatically requested the `tools/list`, and I simply clicked the 'Export' button on the messages panel to download the whole thing. I've attached that exported zipped JSON file here: - [inspector-protocol-rea-2026-10-18T14-18-09.132Z.zip](https://github.com/user-attachments/files/33630188/inspector-protocol-rea-2026-10-18T14-18-09.132Z.zip) The JSON file occupies 20 MB after extraction. Hopefully, this raw dump is exactly what you need to see which specific schema is still choking the Google API.
Author
Owner

@diegoBSousa commented on GitHub (Oct 18, 2026):

I managed to get REA working with Gemini CLI doing two steps:

First I have created a small wrapper to clear the JSON schema in real time:

cat << 'EOF' > ~/.gemini/rea-mcp-sanitize.js
const { spawn } = require('child_process');
const readline = require('readline');

const child = spawn('npx', ['-y', 'rea-agents@6.7.0', 'mcp'], {
  stdio: ['pipe', 'pipe', 'inherit']
});

process.stdin.pipe(child.stdin);

function sanitizeSchema(obj) {
  if (!obj || typeof obj !== 'object') return obj;
  if (Array.isArray(obj)) return obj.map(sanitizeSchema);

  const cleaned = {};
  for (const [k, v] of Object.entries(obj)) {
    if (['$schema', 'additionalProperties', 'default'].includes(k)) continue;
    if (k === 'const') {
      cleaned['enum'] = [String(v)];
      cleaned['type'] = 'string';
      continue;
    }
    if ((k === 'anyOf' || k === 'oneOf') && Array.isArray(v)) {
      const nonNull = v.find(item => item.type !== 'null') || v[0];
      Object.assign(cleaned, sanitizeSchema(nonNull));
      continue;
    }
    cleaned[k] = sanitizeSchema(v);
  }
  return cleaned;
}

const rl = readline.createInterface({ input: child.stdout });
rl.on('line', (line) => {
  try {
    const msg = JSON.parse(line);
    if (msg.result && Array.isArray(msg.result.tools)) {
      msg.result.tools = msg.result.tools.map(t => ({
        ...t,
        inputSchema: sanitizeSchema(t.inputSchema)
      }));
    }
    process.stdout.write(JSON.stringify(msg) + '\n');
  } catch {
    process.stdout.write(line + '\n');
  }
});
EOF

Then I have configured gemini-cli setting to load my sanitizer:
~/.gemini/settings.json

{
  "security": {
    "auth": {
      "selectedType": "gemini-api-key"
    }
  },
  "mcpServers": {
    "rea": {
      "command": "node",
      "args": [
        "/home/path_to_your_home_directory/.gemini/rea-mcp-sanitize.js"
      ]
    }
  },
  "ui": {
    "errorVerbosity": "full"
  }
}

~/.gemini/rea-mcp-sanitize.js

const { spawn } = require('child_process');
const readline = require('readline');

const child = spawn('npx', ['-y', 'rea-agents@6.7.0', 'mcp'], {
  stdio: ['pipe', 'pipe', 'inherit']
});

process.stdin.pipe(child.stdin);

function sanitizeSchema(obj) {
  if (!obj || typeof obj !== 'object') return obj;
  if (Array.isArray(obj)) return obj.map(sanitizeSchema);

  const cleaned = {};
  for (const [k, v] of Object.entries(obj)) {
    if (['$schema', 'additionalProperties', 'default'].includes(k)) continue;
    if (k === 'const') {
      cleaned['enum'] = [String(v)];
      cleaned['type'] = 'string';
      continue;
    }
    if ((k === 'anyOf' || k === 'oneOf') && Array.isArray(v)) {
      const nonNull = v.find(item => item.type !== 'null') || v[0];
      Object.assign(cleaned, sanitizeSchema(nonNull));
      continue;
    }
    cleaned[k] = sanitizeSchema(v);
  }
  return cleaned;
}

const rl = readline.createInterface({ input: child.stdout });
rl.on('line', (line) => {
  try {
    const msg = JSON.parse(line);
    if (msg.result && Array.isArray(msg.result.tools)) {
      msg.result.tools = msg.result.tools.map(t => ({
        ...t,
        inputSchema: sanitizeSchema(t.inputSchema)
      }));
    }
    process.stdout.write(JSON.stringify(msg) + '\n');
  } catch {
    process.stdout.write(line + '\n');
  }
});

It worked like a charm:

Image
<!-- gh-comment-id:6252541853 --> @diegoBSousa commented on GitHub (Oct 18, 2026): I managed to get REA working with Gemini CLI doing two steps: First I have created a small wrapper to clear the JSON schema in real time: ``` cat << 'EOF' > ~/.gemini/rea-mcp-sanitize.js const { spawn } = require('child_process'); const readline = require('readline'); const child = spawn('npx', ['-y', 'rea-agents@6.7.0', 'mcp'], { stdio: ['pipe', 'pipe', 'inherit'] }); process.stdin.pipe(child.stdin); function sanitizeSchema(obj) { if (!obj || typeof obj !== 'object') return obj; if (Array.isArray(obj)) return obj.map(sanitizeSchema); const cleaned = {}; for (const [k, v] of Object.entries(obj)) { if (['$schema', 'additionalProperties', 'default'].includes(k)) continue; if (k === 'const') { cleaned['enum'] = [String(v)]; cleaned['type'] = 'string'; continue; } if ((k === 'anyOf' || k === 'oneOf') && Array.isArray(v)) { const nonNull = v.find(item => item.type !== 'null') || v[0]; Object.assign(cleaned, sanitizeSchema(nonNull)); continue; } cleaned[k] = sanitizeSchema(v); } return cleaned; } const rl = readline.createInterface({ input: child.stdout }); rl.on('line', (line) => { try { const msg = JSON.parse(line); if (msg.result && Array.isArray(msg.result.tools)) { msg.result.tools = msg.result.tools.map(t => ({ ...t, inputSchema: sanitizeSchema(t.inputSchema) })); } process.stdout.write(JSON.stringify(msg) + '\n'); } catch { process.stdout.write(line + '\n'); } }); EOF ``` Then I have configured gemini-cli setting to load my sanitizer: `~/.gemini/settings.json` ``` { "security": { "auth": { "selectedType": "gemini-api-key" } }, "mcpServers": { "rea": { "command": "node", "args": [ "/home/path_to_your_home_directory/.gemini/rea-mcp-sanitize.js" ] } }, "ui": { "errorVerbosity": "full" } } ``` ~/.gemini/rea-mcp-sanitize.js ``` const { spawn } = require('child_process'); const readline = require('readline'); const child = spawn('npx', ['-y', 'rea-agents@6.7.0', 'mcp'], { stdio: ['pipe', 'pipe', 'inherit'] }); process.stdin.pipe(child.stdin); function sanitizeSchema(obj) { if (!obj || typeof obj !== 'object') return obj; if (Array.isArray(obj)) return obj.map(sanitizeSchema); const cleaned = {}; for (const [k, v] of Object.entries(obj)) { if (['$schema', 'additionalProperties', 'default'].includes(k)) continue; if (k === 'const') { cleaned['enum'] = [String(v)]; cleaned['type'] = 'string'; continue; } if ((k === 'anyOf' || k === 'oneOf') && Array.isArray(v)) { const nonNull = v.find(item => item.type !== 'null') || v[0]; Object.assign(cleaned, sanitizeSchema(nonNull)); continue; } cleaned[k] = sanitizeSchema(v); } return cleaned; } const rl = readline.createInterface({ input: child.stdout }); rl.on('line', (line) => { try { const msg = JSON.parse(line); if (msg.result && Array.isArray(msg.result.tools)) { msg.result.tools = msg.result.tools.map(t => ({ ...t, inputSchema: sanitizeSchema(t.inputSchema) })); } process.stdout.write(JSON.stringify(msg) + '\n'); } catch { process.stdout.write(line + '\n'); } }); ``` It worked like a charm: <img width="843" height="594" alt="Image" src="https://github.com/user-attachments/assets/423ec288-e0ec-4ca7-b084-cba9354fcc60" />
Author
Owner

@Nitin13-git commented on GitHub (Oct 18, 2026):

Thanks @diegoBSousa, this is useful: it narrows the Gemini 400 to the schema keywords (not the catalog size alone), and it shows rea-agents@6.7.0 still needs the wrapper.

Your sanitizer removes $schema, additionalProperties and default, rewrites const to a one-value string enum, and collapses anyOf/oneOf to its first non-null branch. I did not run Gemini, so I cannot say which of those Gemini rejects (you removed them together), but here is what REA advertises today. I started rea mcp from current main (b0b485abf) over stdio and scanned the tools/list input schemas (207 tools):

keyword full profile compact profile (REA_MCP_INPUT_SCHEMA_PROFILE=compact)
$schema 207 tools / 207 uses 207 / 207
additionalProperties 207 tools / 1,426 uses 207 / 247
default 68 tools / 287 uses none
const 36 tools / 1,344 uses 10 / 21
anyOf 32 tools / 929 uses 8 / 26
oneOf 31 tools / 201 uses 5 / 5

Separately, the deepest full input schema is 17 levels (compare_web_captures) and compact is 5; Google documents no numeric nesting limit for function declarations (only that deep schemas may be rejected), so I am not claiming depth is the cause.

So the compact profile alone would still send $schema, additionalProperties, const and anyOf to Gemini. If someone can bisect with your wrapper (restore one removed keyword at a time and see which one brings the 400 back), that would identify the exact keyword; a Gemini-specific advertised-schema profile that omits or rewrites just that construct could then be added and verified against a real Gemini run. Nothing here is verified against Gemini yet.

<!-- gh-comment-id:6252654540 --> @Nitin13-git commented on GitHub (Oct 18, 2026): Thanks @diegoBSousa, this is useful: it narrows the Gemini 400 to the schema keywords (not the catalog size alone), and it shows `rea-agents@6.7.0` still needs the wrapper. Your sanitizer removes `$schema`, `additionalProperties` and `default`, rewrites `const` to a one-value string `enum`, and collapses `anyOf`/`oneOf` to its first non-null branch. I did not run Gemini, so I cannot say which of those Gemini rejects (you removed them together), but here is what REA advertises today. I started `rea mcp` from current `main` (`b0b485abf`) over stdio and scanned the `tools/list` input schemas (207 tools): | keyword | `full` profile | `compact` profile (`REA_MCP_INPUT_SCHEMA_PROFILE=compact`) | | --- | --- | --- | | `$schema` | 207 tools / 207 uses | 207 / 207 | | `additionalProperties` | 207 tools / 1,426 uses | 207 / 247 | | `default` | 68 tools / 287 uses | none | | `const` | 36 tools / 1,344 uses | 10 / 21 | | `anyOf` | 32 tools / 929 uses | 8 / 26 | | `oneOf` | 31 tools / 201 uses | 5 / 5 | Separately, the deepest `full` input schema is 17 levels (`compare_web_captures`) and `compact` is 5; Google documents no numeric nesting limit for function declarations (only that deep schemas may be rejected), so I am not claiming depth is the cause. So the `compact` profile alone would still send `$schema`, `additionalProperties`, `const` and `anyOf` to Gemini. If someone can bisect with your wrapper (restore one removed keyword at a time and see which one brings the 400 back), that would identify the exact keyword; a Gemini-specific advertised-schema profile that omits or rewrites just that construct could then be added and verified against a real Gemini run. Nothing here is verified against Gemini yet.
Author
Owner

@ashukumar-tech commented on GitHub (Oct 18, 2026):

I opened a documentation-only diagnostic proposal in #5067 for this Gemini CLI 400 INVALID_ARGUMENT report. It separates MCP registration health (rea doctor --client gemini --json) from model-side schema acceptance, suggests an enabled/disabled REA A/B check, and documents the existing REA_MCP_INPUT_SCHEMA_PROFILE=compact setting without claiming it reduces tool count or fixes every provider limit. This does not claim a runtime fix or a locally reproduced 400; the rejected model request/schema is still needed to establish the root cause. The PR is a draft for review.

<!-- gh-comment-id:6253816204 --> @ashukumar-tech commented on GitHub (Oct 18, 2026): I opened a documentation-only diagnostic proposal in #5067 for this Gemini CLI `400 INVALID_ARGUMENT` report. It separates MCP registration health (`rea doctor --client gemini --json`) from model-side schema acceptance, suggests an enabled/disabled REA A/B check, and documents the existing `REA_MCP_INPUT_SCHEMA_PROFILE=compact` setting without claiming it reduces tool count or fixes every provider limit. This does not claim a runtime fix or a locally reproduced 400; the rejected model request/schema is still needed to establish the root cause. The PR is a draft for review.
Author
Owner

@carcraze commented on GitHub (Oct 19, 2026):

Root cause isolated for the remaining Gemini 400 on rea-agents@6.7.0 — it is not booleans and not catalog size: it is a single advertised empty-string const.

A catalog-wide scan (non-string and empty-string const/enum, full + compact, 207 tools) finds exactly one affected tool: trace_application_feature, at properties.seed.anyOf[1/2/3].properties.value where const: "" is advertised. Clients render that as enum: [""], and Google rejects the whole request with enum[0]: cannot be empty — matching the failing seed -> any_of[1/2/3] -> value -> enum[0] paths exactly. Non-string const/enum: zero in both profiles (the #4025 fix holds).

Filed as #5201 with the exact evidence and a proposed fix (extend the literal presentation to empty-string literals). Inference, not yet a Gemini-verified A/B: removing only the empty-string const values from the advertised schema should clear the 400.

<!-- gh-comment-id:6262049179 --> @carcraze commented on GitHub (Oct 19, 2026): Root cause isolated for the remaining Gemini 400 on `rea-agents@6.7.0` — it is not booleans and not catalog size: it is a single advertised **empty-string** `const`. A catalog-wide scan (non-string **and** empty-string `const`/`enum`, full + compact, 207 tools) finds exactly one affected tool: `trace_application_feature`, at `properties.seed.anyOf[1/2/3].properties.value` where `const: ""` is advertised. Clients render that as `enum: [""]`, and Google rejects the whole request with `enum[0]: cannot be empty` — matching the failing `seed -> any_of[1/2/3] -> value -> enum[0]` paths exactly. Non-string const/enum: zero in both profiles (the #4025 fix holds). Filed as #5201 with the exact evidence and a proposed fix (extend the literal presentation to empty-string literals). Inference, not yet a Gemini-verified A/B: removing only the empty-string `const` values from the advertised schema should clear the 400.
Author
Owner

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

Nice isolation, @carcraze — the empty-string const in trace_application_feature explains why the 400 survived the a2e3016 boolean fix: that fix only handled non-string const values, while const: "" is technically a string but still renders as enum: [""], which Gemini rejects. The #5201 fix direction (extend literal rendering to cover empty-string literals) sounds right. One suggestion: after the fix, also run the same empty-string scan against the compact profile (REA_MCP_INPUT_SCHEMA_PROFILE=compact), since that profile rewrites some schemas and could theoretically introduce or miss the same pattern. That would make the release verification cheap and deterministic.

<!-- gh-comment-id:6262653975 --> @XinwangTao commented on GitHub (Oct 19, 2026): Nice isolation, @carcraze — the empty-string const in trace_application_feature explains why the 400 survived the a2e3016 boolean fix: that fix only handled non-string const values, while `const: ""` is technically a string but still renders as `enum: [""]`, which Gemini rejects. The #5201 fix direction (extend literal rendering to cover empty-string literals) sounds right. One suggestion: after the fix, also run the same empty-string scan against the compact profile (REA_MCP_INPUT_SCHEMA_PROFILE=compact), since that profile rewrites some schemas and could theoretically introduce or miss the same pattern. That would make the release verification cheap and deterministic.
Author
Owner

@aum47 commented on GitHub (Oct 21, 2026):

im having the same issue

<!-- gh-comment-id:6307838385 --> @aum47 commented on GitHub (Oct 21, 2026): im having the same issue
Author
Owner

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

@aum47 If you are on rea-agents@6.7.0, the fastest way to confirm you are hitting the same trigger is to dump tools/list (MCP Inspector's Export button, as ElektroStudios did above) and check trace_application_feature's seed.value for const: "" — carcraze's #5201 scan shows that empty-string literal renders as enum: [""] and is what Gemini rejects with the 400. The earlier boolean-const fix (a2e3016) is already in 6.7.0, so a persistent 400 on 6.7.0 points at the empty-string const. Until the #5201 fix ships, diegoBSousa's sanitizer wrapper in this thread is a working workaround. Also worth verifying against the compact profile (REA_MCP_INPUT_SCHEMA_PROFILE=compact) so the release check is deterministic.

<!-- gh-comment-id:6311182486 --> @XinwangTao commented on GitHub (Oct 21, 2026): @aum47 If you are on rea-agents@6.7.0, the fastest way to confirm you are hitting the same trigger is to dump tools/list (MCP Inspector's Export button, as ElektroStudios did above) and check trace_application_feature's seed.value for const: "" — carcraze's #5201 scan shows that empty-string literal renders as enum: [""] and is what Gemini rejects with the 400. The earlier boolean-const fix (a2e3016) is already in 6.7.0, so a persistent 400 on 6.7.0 points at the empty-string const. Until the #5201 fix ships, diegoBSousa's sanitizer wrapper in this thread is a working workaround. Also worth verifying against the compact profile (REA_MCP_INPUT_SCHEMA_PROFILE=compact) so the release check is deterministic.
Author
Owner

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

Strong isolation @carcraze — the empty-string const being the sole remaining trigger explains why both the boolean fix (a2e3016) and the catalog-size mitigation were necessary but individually insufficient. Since we now have a deterministic scan (non-string + empty-string const/enum over full and compact profiles), I'd suggest making it a release gate: a CI check that fails when any advertised schema contains const or enum values that are empty or non-string, run against both profiles. That turns this class of "Gemini 400 after release" bug into a build-time error, and it would have caught all three rounds (booleans, empty strings, future literal edge cases) before they shipped.

<!-- gh-comment-id:6311202306 --> @XinwangTao commented on GitHub (Oct 21, 2026): Strong isolation @carcraze — the empty-string const being the sole remaining trigger explains why both the boolean fix (a2e3016) and the catalog-size mitigation were necessary but individually insufficient. Since we now have a deterministic scan (non-string + empty-string const/enum over full and compact profiles), I'd suggest making it a release gate: a CI check that fails when any advertised schema contains const or enum values that are empty or non-string, run against both profiles. That turns this class of "Gemini 400 after release" bug into a build-time error, and it would have caught all three rounds (booleans, empty strings, future literal edge cases) before they shipped.
Author
Owner

@Nitin13-git commented on GitHub (Oct 21, 2026):

Correction to my earlier comment: I listed many keywords (additionalProperties, $schema, const, anyOf and others) as suspects. That was too broad. @carcraze isolated the actual remaining trigger in #5201: one tool, trace_application_feature, advertised an empty-string const (seed.value), which clients render as enum: [""], and Gemini rejects with enum[0]: cannot be empty. The compact profile did not help because that value was advertised there too, and @diegoBSousa's wrapper worked because it rewrote that const.

I re-checked current main (3dbe314ad) with a stdio tools/list scan of all 213 tools (full profile): no tool advertises an empty-string const or enum member in its input schema, and trace_application_feature's seed is a plain typed field there. Only its output schema still contains const: "" (3 places); I do not know of a client that sends output schemas to Gemini as function parameters. So the trigger reported in #5201 looks fixed on main, but it is not in a release: npm latest is still 6.7.0, which per #5201's scan still has it. I have not run Gemini CLI, so this is not confirmed against Gemini.

@ElektroStudios @aum47: once a release newer than 6.7.0 is published (or from a fresh build of main), could you retest and say whether the 400 is gone? If it persists, the exact function_declarations[n]... path from the error would show whether something else is left.

<!-- gh-comment-id:6326407458 --> @Nitin13-git commented on GitHub (Oct 21, 2026): Correction to my earlier comment: I listed many keywords (`additionalProperties`, `$schema`, `const`, `anyOf` and others) as suspects. That was too broad. @carcraze isolated the actual remaining trigger in #5201: one tool, `trace_application_feature`, advertised an empty-string `const` (`seed.value`), which clients render as `enum: [""]`, and Gemini rejects with `enum[0]: cannot be empty`. The `compact` profile did not help because that value was advertised there too, and @diegoBSousa's wrapper worked because it rewrote that `const`. I re-checked current `main` (`3dbe314ad`) with a stdio `tools/list` scan of all 213 tools (full profile): no tool advertises an empty-string `const` or `enum` member in its input schema, and `trace_application_feature`'s `seed` is a plain typed field there. Only its output schema still contains `const: ""` (3 places); I do not know of a client that sends output schemas to Gemini as function parameters. So the trigger reported in #5201 looks fixed on `main`, but it is not in a release: npm `latest` is still 6.7.0, which per #5201's scan still has it. I have not run Gemini CLI, so this is not confirmed against Gemini. @ElektroStudios @aum47: once a release newer than 6.7.0 is published (or from a fresh build of `main`), could you retest and say whether the 400 is gone? If it persists, the exact `function_declarations[n]...` path from the error would show whether something else is left.
Author
Owner

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

Agreed — the corrected scope is much tighter and matches the evidence: additionalProperties/$schema/anyOf were red herrings, and the empty-string const in trace_application_feature's seed.value (rendered as enum: [""]) is the actual trigger that survived both the a2e3016 boolean fix and the catalog-size mitigation. One follow-up worth adding to the release gate: since the remaining const: "" occurrences are in the output schema (3 places) rather than the input schema, the scan should cover both input and output schemas across full and compact profiles. Clients don't currently send output schemas to Gemini as parameters, but keeping the gate symmetric avoids a future regression if that ever changes — and it makes the pre-release check deterministic on both sides.

<!-- gh-comment-id:6330397901 --> @XinwangTao commented on GitHub (Oct 22, 2026): Agreed — the corrected scope is much tighter and matches the evidence: additionalProperties/$schema/anyOf were red herrings, and the empty-string const in trace_application_feature's seed.value (rendered as enum: [""]) is the actual trigger that survived both the a2e3016 boolean fix and the catalog-size mitigation. One follow-up worth adding to the release gate: since the remaining const: "" occurrences are in the output schema (3 places) rather than the input schema, the scan should cover both input and output schemas across full and compact profiles. Clients don't currently send output schemas to Gemini as parameters, but keeping the gate symmetric avoids a future regression if that ever changes — and it makes the pre-release check deterministic on both sides.
Author
Owner

@ElektroStudios commented on GitHub (Oct 26, 2026):

@ElektroStudios @aum47: once a release newer than 6.7.0 is published (or from a fresh build of main), could you retest and say whether the 400 is gone? If it persists, the exact function_declarations[n]... path from the error would show whether something else is left.

I've tested v6.8.0, it finally works as expected with no 400 error code. I think this issue could be closed unless someone experiences the same issue.

<!-- gh-comment-id:6405858222 --> @ElektroStudios commented on GitHub (Oct 26, 2026): > @ElektroStudios @aum47: once a release newer than 6.7.0 is published (or from a fresh build of `main`), could you retest and say whether the 400 is gone? If it persists, the exact `function_declarations[n]...` path from the error would show whether something else is left. I've tested v6.8.0, it finally works as expected with no 400 error code. I think this issue could be closed unless someone experiences the same issue.
Author
Owner

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

Confirmed — the v6.8.0 retest matches the expected outcome: the #5201 empty-string const fix (trace_application_feature seed.value) is what actually cleared the 400, after the earlier boolean-const fix (a2e3016) and the catalog-size mitigation each proved necessary but insufficient on their own. Thanks @carcraze for isolating the single remaining trigger and @ElektroStudios for verifying on 6.8.0 — this closes the loop on the whole boolean → empty-string const chain, and the release-gate scan will keep this class of bug from shipping again.

<!-- gh-comment-id:6405988229 --> @XinwangTao commented on GitHub (Oct 26, 2026): Confirmed — the v6.8.0 retest matches the expected outcome: the #5201 empty-string const fix (trace_application_feature seed.value) is what actually cleared the 400, after the earlier boolean-const fix (a2e3016) and the catalog-size mitigation each proved necessary but insufficient on their own. Thanks @carcraze for isolating the single remaining trigger and @ElektroStudios for verifying on 6.8.0 — this closes the loop on the whole boolean → empty-string const chain, and the release-gate scan will keep this class of bug from shipping again.
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#2403
No description provided.