Commit graph

1 commit

Author SHA1 Message Date
GaryOcean
1448718fca
fix: strip output-only fallback blocks from request messages (#1870)
Anthropic's server-side refusal-fallback feature
(`server-side-fallback-2026-06-01`) can emit an output-only `{ "type":
"fallback", ... }` block inside an assistant response. That block is
valid on the response path but rejected on the request path, so when a
client replays the assistant turn the next request can 400 with an
invalid `fallback` input tag.

This strips output-only request blocks in the shared request-body
readers before forwarding. `read_request_json_with_bytes` re-encodes raw
bytes only when stripping occurs, so byte-faithful passthrough paths
cannot leak the invalid block while clean requests keep their original
bytes. If stripping empties an assistant content array, the helper
backfills a benign text block so the request remains schema-valid.

## Type of Change

- [x] Bug fix

## Changes Made

- Add `strip_output_only_request_blocks` in `headroom/proxy/helpers.py`.
- Strip fallback blocks in both `_read_request_json` and
`read_request_json_with_bytes`.
- Add regression tests for stripping, empty-turn backfill, raw-byte
re-encoding, and byte-identical clean requests.
- Update `CHANGELOG.md`.

## Testing

Focused verification on the current PR head after merging `main`:

```text
python -m pytest tests/test_output_only_request_blocks.py -q
4 passed

uvx ruff==0.15.17 check headroom/proxy/helpers.py tests/test_output_only_request_blocks.py
All checks passed!

uvx ruff==0.15.17 format --check headroom/proxy/helpers.py tests/test_output_only_request_blocks.py
2 files already formatted
```

## Notes

No live Anthropic request was run; the regression is covered at the
shared request-reader layer used by the proxy forwarding paths.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: JerrettDavis <mxjerrett@gmail.com>
Co-authored-by: Tejas Chopra <chopratejas@gmail.com>
2026-07-13 14:01:48 -04:00