Skip to content

DecompressionStream: report the codec's code and cause on the TypeError of a failed stream - #47272

Open
robobun wants to merge 4 commits into
mainfrom
robobun/fec0ec66/decompression-stream-zlib-codes
Open

robobun wants to merge 4 commits into
mainfrom
robobun/fec0ec66/decompression-stream-zlib-codes

Conversation

@robobun

@robobun robobun commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

  • On 1.4.x, fileTypeFromBuffer() (file-type 21.3.1 to 22.1.1) rejects with TypeError: inflate failed for a ZIP with a corrupt entry. Node.js and 1.3.14 return { ext: "zip" }. The package needs error.code, which a failed DecompressionStream lost in 1.4.0.
  • Cause: CompressionStreamCoder::run (src/runtime/webcore/CompressionStreamCoder.rs:490 on main) made CodecError::Message(&'static str) of every codec failure (webstreams: native CompressionStream/DecompressionStream/TextEncoderStream/TextDecoderStream #36695).

Fix

  • CodecError::Codec(Failure) keeps the zlib return code and msg, the brotli or zstd code, or Truncated. Message is gone: run cannot return a bare label.
  • Failure::to_js builds Node's error for all five formats: a TypeError, no message, own code. cause is the node:zlib Error for the same bytes.
  • Verified: test/js/web/streams/compression.test.ts (30 new tests, 29 fail on main). Other suites: Notes.

Background

Downsides

Notes

No issue reports this. It came from a differential run against Node.js and Bun 1.3.14. The consequence is a rejected promise or a wrong status on malformed input: no crash, no data loss, nothing on a valid stream. file-type 22.2.0 no longer needs the code. 21.3.4 is the last 21.x.

The report's script (gzip, deflate, deflate-raw: input that ends early, a wrong checksum, another format; 7 rows). Rows that lack the code: 0 on Node.js v26.3.0 and v26.12.1, 0 on Bun 1.3.14, 7 on Bun 1.4.0, 1.4.4 and main 11c3671, 0 on this branch.

Users of the shape, run here.

  • file-type 21.3.4 and 22.1.1 (core.js: recoverableZipErrorCodes has Z_BUF_ERROR, Z_DATA_ERROR, ERR_INVALID_STATE). Five ZIPs, four with a corrupt or cut-off entry: Node.js and 1.3.14 resolve 5 of 5, 1.4.4 resolves 1 of 5, this branch 5 of 5.
  • @zip.js/zip.js 2.8.29, 2.15.0 and 2.16.1 (mapInflateStreamError: if (error && error.message) throw error, else Invalid compressed data). Node.js and 1.3.14: mapped. 1.4.4: not mapped. This branch: mapped. 2.17.0 maps on all of them.

The error, per failure. TypeError, no own message, own properties cause (not enumerable) and code (enumerable, writable, configurable). cause is a plain Error with message, errno, code.

failure code cause.message cause.errno
input ends early, or no input (all five formats) Z_BUF_ERROR unexpected end of file -5
gzip, deflate, deflate-raw: corrupt Z_DATA_ERROR zlib's text, for example incorrect header check -3
deflate: header asks for a preset dictionary Z_NEED_DICT Missing dictionary 2
brotli: corrupt ERR__ERROR_FORMAT_PADDING_1 and so on Decompression failed the decoder's code
zstd: corrupt ZSTD_error_prefix_unknown and so on zstd's text the zstd code
  • 32 probe rows (4 formats that Node.js has, 8 inputs each): bytes delivered before the error, class, message, own property names, code and its attributes, cause and its attributes, cause's class, message, keys, errno and code are equal to Node.js v26.3.0 and v26.12.1 on 32 of 32.
  • cause equals what zlib.gunzipSync, inflateSync, inflateRawSync, brotliDecompressSync and zstdDecompressSync throw in Bun for the same bytes. The tests assert this for 20 rows.
  • Cut-off zstd has no sync call to compare with in Bun: zlib.zstdDecompressSync returns without an error (node:zlib: zstd decoder follows Node v26.10.0 across writes and at the end of the input #33413 changes that). Node.js v26.6.0 and v26.12.1 throw Z_BUF_ERROR, unexpected end of file, errno -5 from that call, which is the cause built here (ZstdDecompressContext::GetErrorInfo in src/node_zlib.cc). v26.5.1 returns without an error. Node.js has no zstd stream.
  • read(), the failing write() and close() reject with the same object. This holds on the JS thread, on the thread pool (a chunk over 128 KiB), in a later step of one chunk, and with a native sink (Bun.write).
  • Out of memory stays a RangeError. ERR_TRAILING_JUNK_AFTER_STREAM_END is unchanged.

Changes that users of 1.4.x see.

  • The TypeError has no message. 1.4.x had inflate failed, unexpected end of file, Missing dictionary, brotli decode failed, zstd decode failed. A message on the TypeError (equal to cause.message) is two lines in Failure::to_js. Then @zip.js/zip.js up to 2.16.1 stays not mapped.
  • Corrupt brotli: cause.message was the decoder's name (_ERROR_FORMAT_PADDING_1) and is now Decompression failed, as in node:zlib. cause gets errno and is no longer enumerable.
  • Corrupt zstd gets a ZSTD_error_* code. 1.3.14 had that code on a plain Error. Here it stays a TypeError, as the spec asks.

code is set with put, not through ErrorCode.ts. ErrorCode.ts puts code on a prototype per code (createErrorPrototype in ErrorCode.cpp) and has no entry for the zlib, brotli or zstd names. Node.js, Bun 1.3.14 and the existing brotli test have an own code. #41737 makes code own for ERR_* errors.

Measured on release builds (lto, linux x64) of main 11c3671 and this branch.

  • size_of CodecError / Option<CodecError> / Result<bool, _> / Result<Progress, _>: 24 / 24 / 24 / 24 bytes (main: 24 / 24 / 24 / 24), Send asserted. The asserts compile for linux x64, x86_64-pc-windows-msvc and aarch64-apple-darwin.
  • size bun: text 138,011,918 to 138,012,142 (+224), data and bss equal, file size equal (138,197,144).
  • run(): 4175 bytes (main 4198). codec_error_to_js: 824 (main 462). New: zlib_error 83, zstd_error 39, bun_zstd::error_code_name 40.
  • Instructions inside run() for a typical valid step (gdb nexti, 200 steps, fixed workloads), main to branch: inflate 114 to 117, deflate 99 to 101, brotli decode 86 to 85, brotli encode 80 to 86, zstd decode 89 to 90, zstd encode 75 to 78. The difference is register moves, two alignment nops and a jump to a shared epilogue. No call and no allocation is added. In the inflate arm, the jump table over zlib's return code (one indirect jump) is one conditional branch now.
  • Error objects per failed stream (heapStats, 2000 streams): deflate 1 to 2, brotli 2 to 2, zstd 1 to 2.
  • node:zlib check_error, no-error path (gdb stepi): zlib 13 to 18 instructions (main 13 to 18), zstd 23 (main 48). NativeBrotli.rs is not edited.
  • CompressionStreamCoder__ exports: 5 (main 5). Host functions, codegen rows, C++ files changed: 0.
  • Trimmed executables (both builds linked with --trimmable=on): bun build --compile --trim 84,315,336 to 84,319,432 bytes (+4,096). bun compile --trim: hello world 25,620,680 to 25,620,616 (-64), a DecompressionStream program 38,574,216 to 38,582,408 (+8,192). The output of each trimmed executable equals the untrimmed run. Entry points (7360) and edges between features (332) are equal.

Not changed here, and where it is tracked.

write() of the bad chunk rejects. This PR does not change that. Since 1.4.0, writer.write(badChunk) rejects with the same TypeError that the reader gets. Node.js and Bun 1.3.14 fulfill that write and report the error on the readable side and on close(). The Streams Standard says reject: the transform of these streams throws a TypeError on bad input (Compression Standard, "decompress and enqueue a chunk"), and TransformStreamDefaultControllerPerformTransform ends with "Throw r", which is the result of the write. A program that does not await or catch that promise gets an unhandled rejection, so it exits with code 1 where Node.js and 1.3.14 exit with 0.

  • Run here, bad bytes into gzip, deflate, deflate-raw and brotli: Node.js v26.3.0 and Bun 1.3.14 fulfill the write (0 unhandled rejections, exit 0). Bun 1.4.4 and the canary build 367d939 reject it (1 unhandled rejection, exit 1).
  • Chrome 153 rejects the write too, and the same program gets 1 unhandledrejection event there.
  • With no reader, Chrome 153 keeps the write pending until the first read, for good and for bad input. Bun 1.4.4 settles a first write with no reader (the test a single write completes without a reader attached pins that), so it rejects the bad chunk at once. Node.js fulfills that write.
  • WPT's compression/decompression-corrupt-input.any.js puts .catch() on its own write() and close().
  • The new tests assert that the failing write() rejects with the same object as the read. Whether the standard's way stays is a maintainer's call.

Self-reviewed: 12 concerns raised, 11 addressed. Removed after the review: a rule that made a zero byte after a gzip member trailing junk (it lost 260 bytes of output for a member plus one zero byte in the same chunk). Changed after the review: the TypeError has no message. Rejected: keep that gzip rule here. It is #43719's decision. Not taken from one addressed concern: the fix for the zstd stream with 16 empty chunks, because #47079 has it.

Suites run on the ASan debug build. test/js/web/streams/compression.test.ts (103 pass), the new tests with BUN_JSC_validateExceptionChecks=1, test/js/node/zlib/zlib.test.js and four more files in test/js/node/zlib, test/js/bun/util/zstd.test.ts, test/regression/issue/{18413*,25432,29225}.test.ts, test/js/web/fetch/fetch-{gzip,compress}.test.ts, 63 vendored Node.js tests (test-zlib-*.js, test-whatwg-webstreams-compression.js, test-stream-iter-transform-errors.js), and test-webstreams-compression-bad-chunks.js, test-webstreams-decompression-reject-trailing.js, test-webstreams-compression-buffer-source.js, test-webstreams-adapters-sync-write-error.js, test-zlib-type-error.js. One test timed out when 15 files ran together and passes alone: libdeflate gzip doesn't write past its output buffer in zlib.test.js (5 s limit, 4.1 s alone). Not run by hand: Windows and macOS.

…ream

The native coder kept only a message string for a failed codec call, so
the TypeError of a DecompressionStream had no code. It now keeps what
the codec said (the zlib return code and msg, the brotli decoder error
code, the zstd error code, or that the input ended early) and builds
one TypeError from it, as Node.js does for these streams: no message,
own code, and as cause the Error that node:zlib reports for the same
failure.
@robobun

robobun commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator Author
Updated 6:05 AM PT - Oct 29th, 2026

❌ @robobun, your commit 99e46ba has 1 failures in Build #135156 (All Failures):

  • Failed to create agent for 🐧 13 x64-hardened - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.5c097f64-4a83-4d26-8a32-6e37cea28e11
  • Failed to create agent for 🐧 25.04 x64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.3883b95d-0c1d-4e70-bc3a-79517910f363
  • Failed to create agent for 🐧 25.04 x64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.cdcc2103-33bd-4f40-a7ef-77b31ee094b3
  • Failed to create agent for 🐧 x64 - verify-baseline
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.6a2dd875-db42-4183-bed9-d153c6396796
  • Failed to create agent for 🐧 13 x64 - cargo-test
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.242c65d5-9320-490f-b687-6ee652c7bbd7
  • Failed to create agent for 🐧 25.04 x64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.4b7b9d53-10a5-43bf-93cf-286945307e84
  • Failed to create agent for 🐧 13 x64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.9aa332aa-bd04-475f-99e1-f201594e613c
  • Failed to create agent for 🐧 13 x64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.76d57f40-1c56-4a05-b857-c4e7628443aa
  • Failed to create agent for 🐧 25.04 x64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.aee23059-7350-48ce-9b31-7875db90a93d
  • Failed to create agent for 🐧 13 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.3587e21d-e664-4339-808e-92dd71c15718
  • Failed to create agent for 🐧 25.04 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.8ebefc8f-fb60-4280-ad7e-280da75a2871
  • Failed to create agent for 🐧 13 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.43ca1daa-8b6a-4382-968d-646102d816c0
  • Failed to create agent for 🐧 25.04 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.c09c9482-89e6-42e9-a50b-35458a7bf760
  • Failed to create agent for 🐧 13 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.36b71f19-2a55-444a-94fe-e3abb6e8aba8
  • Failed to create agent for 🐧 25.04 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.a8f80132-9a38-4249-937d-ccc60e28f4e9
  • Failed to create agent for 🐧 13 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.0e8e44db-1ba3-4697-974a-68e29c461f71
  • Failed to create agent for 🐧 13 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.dafbda3d-d327-4d9b-bf78-74cc2a44e526
  • Failed to create agent for 🐧 13 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.8958f0a7-b451-43c2-85d9-b0bcd19dee3d
  • Failed to create agent for 🐧 13 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.4c2bcb0a-f4cc-49c4-b825-859e706aa245
  • Failed to create agent for 🐧 25.04 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.d19d41fb-04a2-4698-8928-bedd824611b6
  • Failed to create agent for 🐧 13 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.aac9f4c7-c73e-41d2-9b8a-abd5b1a8bcc7
  • Failed to create agent for 🐧 13 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.db1ecb6a-2731-47a6-8585-db4d4e931ffb
  • Failed to create agent for 🐧 25.04 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.8a397804-4f49-4910-99f8-e8f9c4837610
  • Failed to create agent for 🐧 25.04 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.16e58439-9ab7-4fa0-96ca-3c9fbd9ee077
  • Failed to create agent for 🐧 13 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.49fec9d1-989b-4ab2-99d0-03d5b4af2401
  • Failed to create agent for 🐧 25.04 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.e7dcdda2-1ce0-4ae9-a55b-b96737307913
  • Failed to create agent for 🐧 25.04 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.0ccdacf4-e9a3-4f17-9f8b-cb817a725b60
  • Failed to create agent for 🐧 13 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.741c74f8-458e-41ca-9731-05465799641e
  • Failed to create agent for 🐧 aarch64 - verify-baseline
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.0adb5e08-9ca4-4833-ad18-05a7554f7d7a
  • Failed to create agent for 🐧 3.23 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.a809709c-4efd-4d1a-8d88-bfeed247dce7
  • Failed to create agent for 🐧 3.23 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.6357dd13-5c32-455d-9def-40800f914f3a
  • Failed to create agent for 🐧 3.23 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.333fd6c0-b7af-4e27-81c7-b25324bddb72
  • Failed to create agent for 🐧 3.23 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.8a9d67f1-3d64-4b18-9a92-755057f2d01a
  • Failed to create agent for 🐧 3.23 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.15d34c90-07b7-4ce4-ae6a-6beec2815bfb
  • Failed to create agent for 🐧 3.23 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.2ea58fe6-5288-488d-928a-3d264a7db8a5
  • Failed to create agent for 🐧 3.23 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.93f1780f-2f2f-4ce9-9341-802b80125c19
  • Failed to create agent for 🐧 3.23 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.34ebb8c2-b32e-4439-b3b5-827fce292ee4
  • Failed to create agent for 🐧 3.23 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.8e1e08c3-6ac2-4743-ae1a-0fa7ec6cf33e
  • Failed to create agent for 🐧 3.23 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.87abfe7a-f231-4aff-adc1-1d06b339d7be
  • Failed to create agent for 🐧 3.23 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.8e76d380-1dd4-4d94-954f-f0baa7c339c0
  • Failed to create agent for 🐧 3.23 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.4d4f642c-fbf1-4fe5-aabf-ab65b0f5ca12
  • Failed to create agent for 🐧 3.23 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.a7ddac2e-c4c5-4bd4-9abf-5269593ea6d5
  • Failed to create agent for 🐧 3.23 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.b23cc3f1-9b5c-464c-b29d-8fc8469cfe0a
  • Failed to create agent for 🐧 3.23 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.0d629fef-bb1d-4c44-b160-0159af0aeed8
  • Failed to create agent for 🐧 3.23 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.de54c369-b37f-4a92-b6ed-0853b5787114
  • Failed to create agent for 🐧 3.23 aarch64 - test-bun
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.4d3fcaa7-201e-4643-8677-d9a55fefc806
  • Failed to create agent for 🐧 aarch64-musl - verify-baseline
  • CapacityLimitExceededThis account has reached its capacity limit. Reach out to your account team for assistance.d12d75bd-6073-417e-8485-5e71da8b8ced

🧪   To try this PR locally:

bunx bun-pr 47272

That installs a local version of the PR into your bun-47272 executable, so you can run:

bun-47272 --bun

@robobun

robobun commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator Author

Status

How I reproduced it: a script writes bad input to new DecompressionStream(format) for gzip, deflate and deflate-raw (input that ends early, a wrong checksum, bytes in another format: 7 rows), reads the stream to its error, and compares error.code with Z_BUF_ERROR or Z_DATA_ERROR.

runtime rows without the code
Node.js v26.3.0, v26.12.1 0 of 7
Bun 1.3.14 0 of 7
Bun 1.4.0, 1.4.4, main 11c3671 7 of 7
this branch 0 of 7

The user case: fileTypeFromBuffer() of file-type 21.3.4 on five ZIPs, four with a corrupt or cut-off entry. Node.js and Bun 1.3.14 resolve 5 of 5. Bun 1.4.4 resolves 1 of 5 and rejects 4 with a TypeError. This branch resolves 5 of 5.

CI: no test of this change failed in any run. The red check is a CI machine problem.

  • The head (99e46ba) is a merge of main into the branch. There was no conflict, and the change is the same seven files.
  • Build #135156 (the head): every build lane passed, and so did all shards of alpine 3.23 x64, debian 13 x64-asan, windows 2019 x64 and windows 11 aarch64. No test job failed. The build is red because CI could not create agents for 47 jobs: EC2 answered CapacityLimitExceeded, so those jobs never started. Eight macOS test jobs wait for an agent.
  • Builds #134824 and #134791 ran this change before the merge of main. Every blocking lane passed in one of the two, macOS x64 and aarch64 included. The two commits differ only in comment lines of CompressionStreamCoder.rs.

To get a green check, a maintainer can retry the canceled jobs of build 135156.

PR: #47272

@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Warning

Review limit reached

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

Next included review available in 31 seconds.

Check out review usage here.

View limit details

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

Learn how review limits work.

Review configuration:

Run configuration
Commits

Reviewing files that changed from the base of the PR and between 3ad3500 and 99e46ba.

Files selected for processing: 7
  • src/runtime/node/zlib/NativeZlib.rs
  • src/runtime/node/zlib/NativeZstd.rs
  • src/runtime/webcore/CompressionStreamCoder.rs
  • src/zlib/stream.rs
  • src/zlib_sys/shared.rs
  • src/zstd/lib.rs
  • test/js/web/streams/compression.test.ts

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between 37a5e3a and 3272707.

Files selected for processing: 7
  • src/runtime/node/zlib/NativeZlib.rs
  • src/runtime/node/zlib/NativeZstd.rs
  • src/runtime/webcore/CompressionStreamCoder.rs
  • src/zlib/stream.rs
  • src/zlib_sys/shared.rs
  • src/zstd/lib.rs
  • test/js/web/streams/compression.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 2 remain after this review.

Walkthrough

Compression stream errors now retain typed codec details and expose codec-specific codes and causes in JavaScript TypeError objects. The changes also update gzip member handling and add decompression error tests across codecs and stream operations.

Changes

Compression stream error handling

Layer / File(s) Summary
Codec error names and messages
src/zlib_sys/shared.rs, src/zstd/lib.rs, src/zlib/stream.rs, src/runtime/node/zlib/NativeZlib.rs, src/runtime/node/zlib/NativeZstd.rs
Zlib and Zstd helpers provide error names and messages. Native callers use the helpers, and ZStream::error_message now returns a static lifetime.
Typed codec failures and stream handling
src/runtime/webcore/CompressionStreamCoder.rs
CompressionStreamCoder retains typed codec errors, reports truncation and trailing data, and returns no coder when codec initialization or configuration fails. Gzip can continue to another member; other inflate formats report trailing data.
JavaScript error conversion and stream tests
src/runtime/webcore/CompressionStreamCoder.rs, test/js/web/streams/compression.test.ts
Codec failures become TypeError objects with a code and a cause containing codec details. Tests cover malformed and truncated input, stream error consistency, file sinks, and gzip members.

Possibly related PRs

  • oven-sh/bun#47073: Replaces the Brotli C backend with Rust APIs and typed decoder errors used by this change.
  • oven-sh/bun#46607: Introduces ZStream, which this change updates to expose static error-message data.
  • oven-sh/bun#47079: Replaces the zstd C backend with typed errors used by this change.

Suggested reviewers: jarred-sumner, dylan-conway

Priority: Normal

Merge Risk: Minimal · previous review 32727

No actionable issue is established for this change; it is mergeable after normal checks.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title names the main change: failed DecompressionStream streams now report the codec's code and cause on the TypeError. The changeset matches this. It adds typed codec errors (zlib, brotli, zstd, …
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 The PR description follows the repository template. It has both required sections: "Problem"/"Fix"/"Background"/"Downsides" cover the purpose, and the "Verified" line and the Notes block give the veri…
Full details: Title check

Explanation

The title names the main change: failed DecompressionStream streams now report the codec's code and cause on the TypeError. The changeset matches this. It adds typed codec errors (zlib, brotli, zstd, truncation), builds a TypeError with an own code and a cause, and adds tests for these shapes. The title is specific, concise, and single-sentence.

Full details: Description check

Explanation

The PR description follows the repository template. It has both required sections: "Problem"/"Fix"/"Background"/"Downsides" cover the purpose, and the "Verified" line and the Notes block give the verification details, including the new test file, the 29-of-30 failing-on-main result, the ASan debug suite runs, and the 32-of-32 probe comparison against Node.js. The template headings "What does this PR do?" and "How did you verify your code works?" are not used verbatim, but their content is present. Gaps: Windows and macOS were not tested, and one test timed out when run with other files, so the verification is partial. The description also states that error.message changes to empty, which is a user-visible behavior change. It is covered under Downsides.

Finishing Touches: 💡 1
🛠️ Fix failing CI checks: 💡
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.

Beyond the inline finding, I also checked the 'static claim on ZStream::error_message (zlib only points msg at string literals or z_errmsg entries, so carrying it from the thread pool is sound), that the new bun_zstd::error_code_name table has an arm for every ZSTD_error_* constant bound in src/zstd/lib.rs, and that every EncodedSlice::latin1 input in Failure::to_js is an ASCII code name.

Extended reasoning...

The change replaces the string-only codec error in src/runtime/webcore/CompressionStreamCoder.rs with a Copy+Send Failure enum and builds a Node-shaped TypeError (own code, non-enumerable cause with message/errno/code), with small helper additions in src/zlib_sys/shared.rs, src/zlib/stream.rs and src/zstd/lib.rs and 30 new tests. It touches no auth, crypto or injection surface; the risk is behavioral compatibility of error codes on malformed input, which is the subject of the inline finding.

Comment thread src/runtime/webcore/CompressionStreamCoder.rs
Comment thread src/runtime/webcore/CompressionStreamCoder.rs Outdated
Comment thread src/runtime/webcore/CompressionStreamCoder.rs Outdated
Comment thread src/runtime/webcore/CompressionStreamCoder.rs Outdated

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code review found no issues

No high-confidence issues detected in this change.

@robobun

robobun commented Oct 29, 2026

Copy link
Copy Markdown
Collaborator Author

Merged main (da867c6) into this branch so that CI runs on a green main. There was no conflict.

  • CI run 134824 was red for reasons outside this PR: agents that EC2 did not create (CapacityLimitExceeded), and test/aot/* tests on the lane test-aot-drawn, whose families also failed on main (builds 134576 and 134732).
  • On a debug build of da867c6 with this branch and eight other open PRs merged in: test/js/web/streams/compression.test.ts passes (103 tests).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants