Skip to content

Fix zstd decompression for multi-frame responses#12268

Open
r266-tech wants to merge 1 commit intoaio-libs:masterfrom
r266-tech:fix-zstd-multi-frame
Open

Fix zstd decompression for multi-frame responses#12268
r266-tech wants to merge 1 commit intoaio-libs:masterfrom
r266-tech:fix-zstd-multi-frame

Conversation

@r266-tech
Copy link

What do these changes do?

Fix zstd decompression failing with ClientPayloadError when a server sends zstd-encoded data in multiple frames (e.g., chunked transfer encoding with separate flushes per chunk).

The root cause is that compression.zstd.ZstdDecompressor cannot handle inputs containing multiple compressed frames — it raises EOFError: Already at the end of a Zstandard frame when encountering a second frame after the first one ends.

This fix:

  • Catches EOFError when a frame ends and creates a new ZstdDecompressor for the next frame
  • Handles multiple frames arriving in a single chunk by checking unused_data
  • Adds a regression test for multi-frame zstd decompression

Are there changes in behavior for the user?

Servers that send zstd responses in multiple frames (which is valid per the zstd spec) will now work correctly instead of raising ClientPayloadError.

Related issue number

Fixes #12234

Checklist

  • Tests added
  • Changes described in CHANGES/12234.bugfix.rst (if applicable)

ZstdDecompressor from compression.zstd cannot handle inputs containing
multiple compressed frames. When a server sends zstd-encoded data in
multiple frames (e.g., chunked transfer encoding with separate flushes),
the decompressor raises EOFError: 'Already at the end of a Zstandard frame'.

This fix:
- Catches EOFError when a frame ends and creates a new decompressor
- Handles multiple frames arriving in a single chunk via unused_data
- Adds a regression test for multi-frame zstd decompression

Fixes aio-libs#12234
@r266-tech r266-tech requested a review from asvetlov as a code owner March 23, 2026 14:50
@codecov
Copy link

codecov bot commented Mar 23, 2026

Codecov Report

❌ Patch coverage is 85.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 99.10%. Comparing base (2602b71) to head (0d4e114).
⚠️ Report is 1 commits behind head on master.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
aiohttp/compression_utils.py 70.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #12268      +/-   ##
==========================================
- Coverage   99.11%   99.10%   -0.01%     
==========================================
  Files         130      130              
  Lines       45432    45451      +19     
  Branches     2400     2401       +1     
==========================================
+ Hits        45028    45043      +15     
- Misses        273      276       +3     
- Partials      131      132       +1     
Flag Coverage Δ
CI-GHA 98.95% <85.00%> (-0.01%) ⬇️
OS-Linux 98.70% <85.00%> (-0.01%) ⬇️
OS-Windows 96.97% <85.00%> (-0.01%) ⬇️
OS-macOS 97.85% <85.00%> (-0.01%) ⬇️
Py-3.10.11 97.40% <85.00%> (-0.01%) ⬇️
Py-3.10.20 97.89% <85.00%> (-0.01%) ⬇️
Py-3.11.15 98.09% <85.00%> (-0.01%) ⬇️
Py-3.11.9 97.61% <85.00%> (-0.01%) ⬇️
Py-3.12.10 97.70% <85.00%> (-0.01%) ⬇️
Py-3.12.13 98.18% <85.00%> (-0.01%) ⬇️
Py-3.13.12 98.42% <85.00%> (-0.01%) ⬇️
Py-3.14.3 98.48% <85.00%> (-0.01%) ⬇️
Py-3.14.3t 97.47% <85.00%> (-0.02%) ⬇️
Py-pypy3.11.13-7.3.20 97.49% <10.00%> (-0.05%) ⬇️
VM-macos 97.85% <85.00%> (-0.01%) ⬇️
VM-ubuntu 98.70% <85.00%> (-0.01%) ⬇️
VM-windows 96.97% <85.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@codspeed-hq
Copy link

codspeed-hq bot commented Mar 23, 2026

Merging this PR will not alter performance

✅ 59 untouched benchmarks


Comparing r266-tech:fix-zstd-multi-frame (0d4e114) with master (2602b71)1

Open in CodSpeed

Footnotes

  1. No successful run was found on master (166f48d) during the generation of this report, so 2602b71 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

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.

ClientPayloadError: 400, message: Can not decode content-encoding: zstd - Already at the end of a Zstandard frame

1 participant