Skip to content

fix(anthropic): return API error for malformed non-streaming responses - #875

Open
leseb wants to merge 1 commit into
praxis-proxy:mainfrom
leseb:leseb/validate-fix-issue-835
Open

fix(anthropic): return API error for malformed non-streaming responses#875
leseb wants to merge 1 commit into
praxis-proxy:mainfrom
leseb:leseb/validate-fix-issue-835

Conversation

@leseb

@leseb leseb commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Summary

The Anthropic-to-OpenAI filter rewrites response headers to advertise an Anthropic response contract, but an upstream can return HTTP 200 with a body that cannot be transformed (malformed JSON, empty, or missing) — previously that broken body was forwarded unchanged, so clients received a response that did not conform to the advertised contract. transform_non_streaming_body now replaces any untransformable success body with a schema-complete Anthropic api_error envelope and preserves the upstream request id (now captured on the success path too). This is the smallest complete change: it only rewrites the body on the failure-to-transform path and leaves successful translations untouched.

Related issue

Closes #835

Validation

  • Unit tests — cargo test -p praxis-ai-apis --lib anthropic (206 passed), covering missing / empty / malformed non-streaming success bodies
  • Integration or functional tests — anthropic_to_openai_replaces_malformed_success_body proxy test and all_inference_fixtures_replay with the new synthetic messages/malformed-success recording
  • make lint (clippy, rustfmt, deps, docs, examples, check-inference, README sync) and make build

Checklist

  • I reviewed every changed line and can explain the change.
  • New capabilities include an example config and functional example test. — bug fix; adds a functional example test against the existing anthropic/messages-to-openai.yaml config.
  • User-facing behavior and generated documentation are updated. — generated inference coverage README regenerated via sync-inference-readme.
  • Performance-sensitive changes include appropriate benchmark or load-test evidence. — N/A; only the failure-to-transform path is affected.
  • Commits are signed and include a Signed-off-by trailer.

Breaking changes

None. Only responses that previously could not be transformed change behavior: instead of a non-conformant body forwarded under Anthropic headers, clients now receive a valid Anthropic api_error envelope. (The HTTP status stays 200 because Praxis 0.5.3 cannot change an already-selected status during response-body processing; exact 500 conformance needs deferred-header support in Praxis core.)

The Anthropic-to-OpenAI filter rewrites response headers to advertise an Anthropic response contract, but an upstream can return HTTP 200 with a body that cannot be transformed (malformed JSON, empty, or missing). Previously the filter forwarded that broken body unchanged under Anthropic headers, so clients received a response that did not conform to the advertised contract.

transform_non_streaming_body now replaces any untransformable success body with a schema-complete Anthropic api_error envelope and preserves the upstream request id (now captured on the success path as well). Adds unit, proxy integration, and synthetic fixture coverage (messages/malformed-success).

Closes praxis-proxy#835

Signed-off-by: Sébastien Han <seb@redhat.com>
@leseb
leseb requested review from a team and alexsnaps September 2, 2026 10:44
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.

Malformed successful Chat Completions responses pass through under an Anthropic response contract

1 participant