Skip to content

fix(passthrough): proxy provider-native error bodies, clean decode errors, cap stop sequences - #966

Open
SantiagoDePolonia wants to merge 3 commits into
mainfrom
fix/passthrough-native-errors
Open

SantiagoDePolonia wants to merge 3 commits into
mainfrom
fix/passthrough-native-errors

Conversation

@SantiagoDePolonia

Copy link
Copy Markdown
Contributor

Fixes three findings from the dialect e2e run (4, 7, 10), each verified against main first.

Passthrough errors are provider-native again (finding 4). docs/features/passthrough-api.mdx promises that provider error bodies and status codes are proxied, but every non-2xx was re-rendered in the gateway's OpenAI envelope, so the Anthropic SDK lost its typed errors and the upstream request_id. /p/{provider} (and the /v1/messages native-forwarding path) now relay the upstream JSON error body, status and content type untouched. Gateway-generated failures — authentication, rate limits, budgets, a provider that is not enabled, an unreachable upstream — keep the gateway's shape, as does an upstream body that is not JSON, is empty, or exceeds 1 MiB. Only the body, its media type and the headers the gateway already relayed on errors cross back, so upstream credentials, cookies and base URLs still cannot leak. Logs and the audit row keep the classified gateway error.

Clean JSON decode errors (finding 7). goccy/go-json wording reached clients verbatim: json: slice unexpected end of JSON input for a complete document, cannot unmarshal number \" for a string value, plus Go struct field names. Decode failures now name the offending member and the type it should have — messages: must be an array, max_tokens: must be an integer, messages[1].role: must be a string — with the member set as param on the OpenAI envelope. Truncated and non-JSON bodies get an honest message instead of a byte-level decoder complaint. The canonical chat/responses types wrap the nested decode error so the position that identifies the member survives their UnmarshalJSON.

stop_sequences beyond four (finding 10). OpenAI, Azure OpenAI and Groq cap stop at four items; Anthropic accepts more, and the Messages API docs say stop sequences are honored on every provider. Following Postel's law the gateway now truncates the list to each provider's limit (logging a warning) instead of letting the request fail upstream over a limit the client cannot know; Anthropic still receives the full list. The Messages API doc records the limit.

Tested

  • go build ./..., go test -race ./internal/..., make lint, make test-race (only the pre-existing TestVersionEndpoint* local/UTC date flake fails).
  • Live gateway against real providers: Anthropic passthrough 400/404 now return {"type":"error",...} with request_id and anthropic-python raises its typed NotFoundError with the native body; gateway auth / disabled-provider errors stay OpenAI-shaped; success bodies still byte-verbatim; malformed bodies on /v1/chat/completions, /v1/messages and /v1/responses return the new messages; six stop sequences now succeed on openai/gpt-4.1-mini and groq/openai/gpt-oss-20b and are still applied in full on Anthropic.

@mintlify

mintlify Bot commented Sep 11, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
gomodel 🟢 Ready View Preview Sep 12, 2026, 8:48 AM

💡 Tip: Enable Automations to automatically generate PRs for you.

@coderabbitai

coderabbitai Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Next included review available in 41 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: bfbb7e37-983c-48dc-9d3c-30957f9f0b47

📥 Commits

Reviewing files that changed from the base of the PR and between 6d042df and 36dc6d3.

📒 Files selected for processing (25)
  • docs/advanced/anthropic-messages-api.mdx
  • docs/features/passthrough-api.mdx
  • internal/core/chat_json.go
  • internal/core/json_errors.go
  • internal/core/json_errors_test.go
  • internal/core/responses_json.go
  • internal/providers/azure/azure.go
  • internal/providers/groq/reasoning.go
  • internal/providers/groq/reasoning_test.go
  • internal/providers/openai/openai.go
  • internal/providers/stop_sequences.go
  • internal/providers/stop_sequences_test.go
  • internal/server/audio_service.go
  • internal/server/error_support.go
  • internal/server/image_service.go
  • internal/server/messages_batch_service.go
  • internal/server/messages_handler.go
  • internal/server/messages_native.go
  • internal/server/native_batch_service.go
  • internal/server/native_conversation_items_service.go
  • internal/server/native_conversation_service.go
  • internal/server/native_response_service.go
  • internal/server/passthrough_support.go
  • internal/server/passthrough_support_test.go
  • internal/server/translated_inference_service.go

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov-commenter

codecov-commenter commented Sep 11, 2026

Copy link
Copy Markdown

@greptile-apps

greptile-apps Bot commented Sep 11, 2026

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

Safe to merge.

Reviews (2) · Last reviewed commit: "Merge origin/main into fix/passthrough-n..."

@SantiagoDePolonia

Copy link
Copy Markdown
Contributor Author

Greptile's finding is addressed in a3d4dcb: the Responses input union is decoded from its own fragment, so its decoder positions are meaningless in the request body. That failure is now tagged with the member it came from and reported as input: must be an object (with param: "input"), and the generic locator additionally discards any position whose member already holds the expected type, so no innocent member can be blamed.

@SantiagoDePolonia

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@SantiagoDePolonia

Copy link
Copy Markdown
Contributor Author

@greptileai review

@coderabbitai

coderabbitai Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Rate Limit Exceeded

@SantiagoDePolonia have exceeded the limit for the number of chat messages per hour. Please wait 22 minutes and 56 seconds before sending another message.

@SantiagoDePolonia

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Rate Limit Exceeded

@SantiagoDePolonia have exceeded the limit for the number of chat messages per hour. Please wait 11 minutes and 48 seconds before sending another message.

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.

2 participants