Skip to content

fix(translation): reject malformed request fields - #287

Merged
nachiketb-nvidia merged 2 commits into
mainfrom
fix/reject-malformed-request-fields
Aug 4, 2026
Merged

fix(translation): reject malformed request fields#287
nachiketb-nvidia merged 2 commits into
mainfrom
fix/reject-malformed-request-fields

Conversation

@nachiketb-nvidia

@nachiketb-nvidia nachiketb-nvidia commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

What

Reject malformed Anthropic system and max_tokens fields and malformed OpenAI Responses input fields during request decoding.

Why

These explicitly invalid values were previously coerced into text or treated as absent. That changed request semantics, allowed malformed requests to reach an upstream model, and could create unintended usage.

Fixes SWITCH-1188.
Fixes SWITCH-1189.
Fixes SWITCH-1190.

How

  • Treat an omitted or null Anthropic system as no system instruction; otherwise require a string or text-block array.
  • Require an explicitly supplied Anthropic max_tokens to be a non-negative integer.
  • Require Responses input to be a string or array.
  • Return path-aware translation errors that the server already exposes as structured HTTP 400 responses.
  • Preserve the existing behavior for omitted fields.

What to review

  • Please review the public error messages specifically, including whether the JSONPath-style field paths are clear and appropriate.
  • The accepted wire types and non-negative-integer constraint.
  • The single table-driven regression test covering all six reported variants across the three tickets.

Live validation

Built the release server from this branch and ran every issue reproducer with live credentials:

Malformed input Direct control Switchyard Switchyard error message
Anthropic system={} or system=true HTTP 400 HTTP 400 expected string or array of text blocks at $.system
Anthropic max_tokens=-1 or max_tokens="8" HTTP 400 HTTP 400 invalid value at $.max_tokens: expected a non-negative integer
Responses input=true or input=null HTTP 500 HTTP 400 expected string or array at $.input

After all six rejected Switchyard requests, /v1/stats reported total_requests: 0, confirming that none reached routing or an upstream model. A valid routed control then returned HTTP 200 and incremented total_requests to 1.

Validation

  • cargo test -p switchyard-translation
  • cargo clippy -p switchyard-translation --all-targets -- -D warnings

Summary by CodeRabbit

  • Bug Fixes
    • Improved request validation for Anthropic and OpenAI Responses integrations.
    • Invalid or missing token limits now return clear validation errors.
    • Unsupported system and input field formats are rejected instead of being silently converted to text.
    • Added coverage for malformed request fields to help prevent regressions.

Signed-off-by: nachiketb <nachiketb@nvidia.com>
@nachiketb-nvidia
nachiketb-nvidia requested a review from a team as a code owner August 4, 2026 19:00
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Request decoding now validates Anthropic max_tokens and system fields. Responses decoding rejects unsupported input types. Regression tests cover the malformed request cases and expected validation errors.

Changes

Request validation

Layer / File(s) Summary
Anthropic field validation
crates/switchyard-translation/src/codecs/anthropic/buffered.rs
Anthropic decoding requires positive max_tokens values and supported system values. Unsupported system types return InvalidType.
Responses input validation
crates/switchyard-translation/src/codecs/responses/buffered.rs, crates/switchyard-translation/tests/request_translation.rs
Responses decoding rejects non-string, non-array input values. Regression tests cover malformed Anthropic and Responses fields.

Estimated code review effort: 2 (Simple) | ~10 minutes

Poem

A rabbit checks each token twice,
Rejects bad shapes, precise and nice.
System text must match the form,
Strange inputs meet an error storm.
Tests hop after, all green and bright.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: rejecting malformed request fields during translation.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/switchyard-translation/src/codecs/anthropic/buffered.rs (1)

347-374: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reject invalid entries in a system array.

The decoder accepts an array that contains non-object blocks, non-text blocks, or a text block with a non-string text member. Lines 356-365 silently discard or coerce those entries. For example, {"system":[{"type":"image"},{"type":"text","text":7}]} decodes successfully with changed instruction content.

Validate every array member as a text block. Return a TranslationError with the indexed path when validation fails. Add regression cases for invalid array members.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/switchyard-translation/src/codecs/anthropic/buffered.rs` around lines
347 - 374, Update decode_anthropic_system so every array member must be an
object with type "text" and a string text field; return TranslationError with
the member’s indexed path for any invalid entry instead of skipping or
defaulting it. Preserve valid string and text-block decoding, and add regression
cases covering non-object, non-text, and non-string text members.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@crates/switchyard-translation/src/codecs/anthropic/buffered.rs`:
- Around line 347-374: Update decode_anthropic_system so every array member must
be an object with type "text" and a string text field; return TranslationError
with the member’s indexed path for any invalid entry instead of skipping or
defaulting it. Preserve valid string and text-block decoding, and add regression
cases covering non-object, non-text, and non-string text members.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9db98ce9-193c-4d6c-91d5-6067aaf1325b

📥 Commits

Reviewing files that changed from the base of the PR and between 0e99eb4 and c01f29a.

📒 Files selected for processing (3)
  • crates/switchyard-translation/src/codecs/anthropic/buffered.rs
  • crates/switchyard-translation/src/codecs/responses/buffered.rs
  • crates/switchyard-translation/tests/request_translation.rs

@nachiketb-nvidia
nachiketb-nvidia force-pushed the fix/reject-malformed-request-fields branch from c9c0251 to 0385596 Compare August 4, 2026 19:22
Signed-off-by: nachiketb <nachiketb@nvidia.com>
@nachiketb-nvidia
nachiketb-nvidia force-pushed the fix/reject-malformed-request-fields branch from 0385596 to ea8d20e Compare August 4, 2026 19:24
@nachiketb-nvidia
nachiketb-nvidia enabled auto-merge (squash) August 4, 2026 19:28
@nachiketb-nvidia
nachiketb-nvidia merged commit eea4e01 into main Aug 4, 2026
17 checks passed
@nachiketb-nvidia
nachiketb-nvidia deleted the fix/reject-malformed-request-fields branch August 4, 2026 19:31
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