Skip to content

fix(translator): normalize Gemini contents to prevent 400 invalid_argument - #2192

Closed
warelik wants to merge 1 commit into
decolua:masterfrom
warelik:fix/gemini-contents-normalize
Closed

warelik wants to merge 1 commit into
decolua:masterfrom
warelik:fix/gemini-contents-normalize

Conversation

@warelik

@warelik warelik commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Resolves #2191

Summary

When translating OpenAI/Claude request payloads to the Gemini API format, the resulting request payload can contain consecutive same-role messages (e.g. adjacent user messages from system/user prompts or tool history conversion) or empty parts. This causes the Gemini API to reject the request with 400 INVALID_ARGUMENT.

This PR introduces a normalizeGeminiContents helper to safely merge adjacent same-role content blocks and strip empty parts, ensuring fully normalized payloads.

Changes

  • open-sse/translator/request/openai-to-gemini.js:
    • Implemented normalizeGeminiContents to concatenate parts of adjacent same-role blocks and filter out empty roles/parts.
    • Normalized result.contents in openaiToGeminiBase (affects standard OpenAI to Gemini and Gemini CLI requests).
    • Normalized envelope.request.contents in wrapInCloudCodeEnvelopeForClaude (affects Anthropic/Claude to Gemini conversions).

@decolua

decolua commented Jun 29, 2026

Copy link
Copy Markdown
Owner

Thanks @warelik for the fix! Merging adjacent same-role blocks and stripping empty parts is the right way to avoid Gemini's 400 INVALID_ARGUMENT. We've reviewed and applied this. 🙏

@decolua

decolua commented Jun 29, 2026

Copy link
Copy Markdown
Owner

Thanks @warelik for the fix! Merging adjacent same-role blocks and stripping empty parts is the right way to avoid Gemini's 400 INVALID_ARGUMENT. Reviewed and applied. 🙏

@decolua decolua closed this Jun 29, 2026
decolua pushed a commit that referenced this pull request Jun 29, 2026
Merge adjacent same-role blocks and strip empty parts before sending to
Gemini, avoiding 400 INVALID_ARGUMENT on consecutive same-role messages.

Co-authored-by: Cursor <cursoragent@cursor.com>
decolua pushed a commit that referenced this pull request Jun 29, 2026
## Features
- Add Kimchi OAuth provider — Nant361
- Refine Qwen vision/video + thinking model patterns — decolua
- Opt-in Codex auto-ping quota keep-alive — Emirhan

## Fixes
- **Responses**: handle response.done terminal events (#2142) — rifuki
- **Headroom**: skip unsafe responses tool history (#2132) — Sutarto Jordan Chrisfivo
- **Translator**: map mid-conversation system message to user (claude→openai) — decolua
- **Gemini**: normalize contents to prevent 400 invalid_argument (#2192) — warelik
- **Gemini**: backfill thoughtSignature + suppress stream done sentinel — WARELIK
- **Alicode**: preserve cache_control for DashScope providers (#2069) — Rex
- **Antigravity**: strip deprecated/readOnly/writeOnly from tool schemas — iletai, Yudhistira-Official
- **CodeBuddy CN**: show bonus packs as one-time, not monthly-replenishing — whale9820
- **Kiro**: strip leaked <thinking> tags from content stream (#2158) — hamsa0x7
- **Tray**: make Windows context menu DPI-aware — Emirhan
- **Kilocode**: expose full gateway catalog in combo model picker — jellylarper
- **OpenCode**: fix Go GLM — decolua
Vanszs pushed a commit to Vanszs/VansRouter that referenced this pull request Jun 30, 2026
…lua#2192)

Merge adjacent same-role blocks and strip empty parts before sending to
Gemini, avoiding 400 INVALID_ARGUMENT on consecutive same-role messages.

Co-authored-by: Cursor <cursoragent@cursor.com>
Vanszs added a commit to Vanszs/VansRouter that referenced this pull request Jun 30, 2026
Bump version to 0.7.7 and add CHANGELOG entry covering the 22 commits
on dev since v0.7.6:

- 18 source fixes: translator (cache_control, mid-conv system→user,
  response.done terminal), kiro (randomUUID, thinking-strip), headroom
  (openai-responses translation, skip unsafe Responses tool history),
  antigravity (schema deprecated/readOnly/writeOnly strip for Gemini),
  alicode (cache_control for DashScope, decolua#2069), kilocode (full
  gateway catalog in combo picker), gemini (thoughtSignature backfill,
  contents normalize, decolua#2192), OpenCode Go (GLM routing), tray
  (Windows context menu DPI-aware), token-saver (full-width card layout),
  capabilities (Qwen vision/video/thinking patterns)
- Snapshot update for v0.7.6 + new regression tests
  (alicode-cache-control-2069, kiro-thinking-strip, updated
  openai-responses-terminal-event)
- Docs: AGENTS.md release pipeline rules (3 lessons from v0.7.5→v0.7.6)
- Chore: untrack .kimchi/docs/lighthouse-reports/ (20 generated HTML/JSON
  artifacts; .kimchi/ now in .gitignore so they won't be re-added)

Verified on dev:
- pnpm test tests/unit/runtime-detect.test.js → 24/24 pass
- pnpm test (full) → 1847 pass + 14 pre-existing all-endpoints-robust
  401-Invalid-API-key failures (confirmed pre-existing on main before
  this release; not a regression)
- pnpm run build → build complete (no-undef lint: clean)
- pnpm lint:undef → clean
Vanszs added a commit to Vanszs/VansRouter that referenced this pull request Jun 30, 2026
…repo maintenance)

Brings in 22 commits from dev since v0.7.6:
- 18 source fixes (translator cache_control/mid-conv system→user/response.done,
  kiro randomUUID/thinking-strip, headroom openai-responses/unsafe Responses
  tool history, antigravity schema deprecated/readOnly/writeOnly strip for
  Gemini, alicode cache_control for DashScope decolua#2069, kilocode full gateway
  catalog, gemini thoughtSignature backfill/contents normalize decolua#2192,
  OpenCode Go GLM routing, tray Windows context menu DPI-aware,
  token-saver full-width card layout, capabilities Qwen vision/video/thinking)
- Snapshot update for v0.7.6 + new regression tests
- Docs: AGENTS.md release pipeline rules (3 lessons from v0.7.5→v0.7.6)
- Chore: untrack .kimchi/docs/lighthouse-reports/ (20 generated HTML/JSON
  artifacts; .kimchi/ now in .gitignore so they won't be re-added)
- Bump to v0.7.7
ibanunmangun pushed a commit to ibanunmangun/9router that referenced this pull request Jul 22, 2026
…lua#2192)

Merge adjacent same-role blocks and strip empty parts before sending to
Gemini, avoiding 400 INVALID_ARGUMENT on consecutive same-role messages.

Co-authored-by: Cursor <cursoragent@cursor.com>
ibanunmangun pushed a commit to ibanunmangun/9router that referenced this pull request Jul 22, 2026
## Features
- Add Kimchi OAuth provider — Nant361
- Refine Qwen vision/video + thinking model patterns — decolua
- Opt-in Codex auto-ping quota keep-alive — Emirhan

## Fixes
- **Responses**: handle response.done terminal events (decolua#2142) — rifuki
- **Headroom**: skip unsafe responses tool history (decolua#2132) — Sutarto Jordan Chrisfivo
- **Translator**: map mid-conversation system message to user (claude→openai) — decolua
- **Gemini**: normalize contents to prevent 400 invalid_argument (decolua#2192) — warelik
- **Gemini**: backfill thoughtSignature + suppress stream done sentinel — WARELIK
- **Alicode**: preserve cache_control for DashScope providers (decolua#2069) — Rex
- **Antigravity**: strip deprecated/readOnly/writeOnly from tool schemas — iletai, Yudhistira-Official
- **CodeBuddy CN**: show bonus packs as one-time, not monthly-replenishing — whale9820
- **Kiro**: strip leaked <thinking> tags from content stream (decolua#2158) — hamsa0x7
- **Tray**: make Windows context menu DPI-aware — Emirhan
- **Kilocode**: expose full gateway catalog in combo model picker — jellylarper
- **OpenCode**: fix Go GLM — decolua
Shinzzyak pushed a commit to Shinzzyak/VansRouter that referenced this pull request Sep 11, 2026
…lua#2192)

Merge adjacent same-role blocks and strip empty parts before sending to
Gemini, avoiding 400 INVALID_ARGUMENT on consecutive same-role messages.

Co-authored-by: Cursor <cursoragent@cursor.com>
Shinzzyak pushed a commit to Shinzzyak/VansRouter that referenced this pull request Sep 11, 2026
Bump version to 0.7.7 and add CHANGELOG entry covering the 22 commits
on dev since v0.7.6:

- 18 source fixes: translator (cache_control, mid-conv system→user,
  response.done terminal), kiro (randomUUID, thinking-strip), headroom
  (openai-responses translation, skip unsafe Responses tool history),
  antigravity (schema deprecated/readOnly/writeOnly strip for Gemini),
  alicode (cache_control for DashScope, decolua#2069), kilocode (full
  gateway catalog in combo picker), gemini (thoughtSignature backfill,
  contents normalize, decolua#2192), OpenCode Go (GLM routing), tray
  (Windows context menu DPI-aware), token-saver (full-width card layout),
  capabilities (Qwen vision/video/thinking patterns)
- Snapshot update for v0.7.6 + new regression tests
  (alicode-cache-control-2069, kiro-thinking-strip, updated
  openai-responses-terminal-event)
- Docs: AGENTS.md release pipeline rules (3 lessons from v0.7.5→v0.7.6)
- Chore: untrack .kimchi/docs/lighthouse-reports/ (20 generated HTML/JSON
  artifacts; .kimchi/ now in .gitignore so they won't be re-added)

Verified on dev:
- pnpm test tests/unit/runtime-detect.test.js → 24/24 pass
- pnpm test (full) → 1847 pass + 14 pre-existing all-endpoints-robust
  401-Invalid-API-key failures (confirmed pre-existing on main before
  this release; not a regression)
- pnpm run build → build complete (no-undef lint: clean)
- pnpm lint:undef → clean
Shinzzyak pushed a commit to Shinzzyak/VansRouter that referenced this pull request Sep 11, 2026
…repo maintenance)

Brings in 22 commits from dev since v0.7.6:
- 18 source fixes (translator cache_control/mid-conv system→user/response.done,
  kiro randomUUID/thinking-strip, headroom openai-responses/unsafe Responses
  tool history, antigravity schema deprecated/readOnly/writeOnly strip for
  Gemini, alicode cache_control for DashScope decolua#2069, kilocode full gateway
  catalog, gemini thoughtSignature backfill/contents normalize decolua#2192,
  OpenCode Go GLM routing, tray Windows context menu DPI-aware,
  token-saver full-width card layout, capabilities Qwen vision/video/thinking)
- Snapshot update for v0.7.6 + new regression tests
- Docs: AGENTS.md release pipeline rules (3 lessons from v0.7.5→v0.7.6)
- Chore: untrack .kimchi/docs/lighthouse-reports/ (20 generated HTML/JSON
  artifacts; .kimchi/ now in .gitignore so they won't be re-added)
- Bump to v0.7.7
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.

[Bug] Gemini API returns 400 INVALID_ARGUMENT on consecutive same-role messages or empty content parts

2 participants