Skip to content

fix: preserve Pako decompression errors when reading objects - #2451

Merged
jcubic merged 9 commits into
isomorphic-git:mainfrom
snowyukitty:fix/inflate-error-diagnostics
Oct 12, 2026
Merged

jcubic merged 9 commits into
isomorphic-git:mainfrom
snowyukitty:fix/inflate-error-diagnostics

Conversation

@snowyukitty

@snowyukitty snowyukitty commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Pako can throw strings when reading a corrupt loose object. The public command then tries to attach its caller name, masking the decompression diagnostic with a TypeError.

Normalize Pako string failures to DecompressionError, a new BaseError subclass exported through Errors. It retains the diagnostic in its message and data, supports the existing error serialization contract, and identifies corrupt compressed input without InternalError's library-bug guidance. Existing Error instances keep their identity.

Await the native decompression path and normalize its empty TypeError failures in nativeInflate to the same error type with a nonempty diagnostic. Informative native errors are preserved. Native-backend activation remains unchanged; #1932 and #1799 cover that separately.

Regression tests cover inflate, readTree and readObject in regular repositories and submodules, decompressed formats, unchanged deflated passthrough, valid streams, asynchronous native failures, caller attachment and error serialization. Local metadata casts keep direct-source JavaScript typechecking compatible with BaseError's existing runtime shape and fromJSON return contract.

Refs #1833.

Current-revision validation in isolated Linux containers on Node 22 and Node 24: changed-file lint, Rollup, declarations, native JavaScript typecheck and eleven focused suites passed (97 tests and 36 snapshots per runtime). The real [0,0] DecompressionStream example is now a regression test: an empty native TypeError is normalized with classification and serialization preserved, while informative native errors retain their name and message. These are focused checks; the full Node/browser suites and a Chromium smoke test were not run for this revision.

Merged main at 909b97b1617b, preserving every upstream contributor and the existing contribution record. Restored literal Unicode names in .all-contributorsrc without changing its parsed data; regenerating the contributor table leaves README unchanged. The focused run also includes the upstream packfile-integrity suite.

The shared helper, module and focused test are named nativeInflate, reflecting support in both Node.js and browsers. The maintainer's direct [0,0] DecompressionStream example was reproduced on Node 22 and 24: the native API throws an empty TypeError, while the helper reports DecompressionError with a nonempty diagnostic.

@coderabbitai

coderabbitai Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e3ab4154-0f4d-41b5-86b7-296a7b4c092c

📥 Commits

Reviewing files that changed from the base of the PR and between d899055 and e5b405d.


📒 Files selected for processing (15)
  • .all-contributorsrc
  • README.md
  • __tests__/test-GitError-in-submodule.js
  • __tests__/test-GitError.js
  • __tests__/test-browserInflate.js
  • __tests__/test-inflate.js
  • __tests__/test-readObject-in-submodule.js
  • __tests__/test-readObject.js
  • __tests__/test-readTree-in-submodule.js
  • __tests__/test-readTree.js
  • src/errors/BaseError.js
  • src/errors/DecompressionError.js
  • src/errors/index.js
  • src/utils/browserInflate.js
  • src/utils/inflate.js

🚧 Files skipped from review as they are similar to previous changes (2)
  • README.md
  • .all-contributorsrc

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



📝 Walkthrough
📝 Walkthrough
📝 Walkthrough
📝 Walkthrough
📝 Walkthrough

Walkthrough

The change adds DecompressionError and updates inflate to normalize string errors. Tests cover valid and corrupt compressed data in direct inflation, object reads, and tree reads. The contributor records add snowyukitty.

Changes

Inflate Error Handling

Layer / File(s) Summary
Decompression error type and serialization
src/errors/DecompressionError.js, src/errors/BaseError.js, src/errors/index.js, __tests__/test-GitError*.js
Adds and exports DecompressionError, which sets its code and name, prefixes its message, and stores the supplied message in data. BaseError accesses code and data through any-typed locals. Tests cover error properties and JSON restoration.
Inflate error normalization and direct tests
src/utils/browserInflate.js, src/utils/inflate.js, __tests__/__helpers__/corruptZlib.js, __tests__/test-browserInflate.js, __tests__/test-inflate.js
inflate uses the separate browserInflate function and converts string errors to DecompressionError. browserInflate converts empty-message TypeError values to a decompression error and rethrows other errors. Tests cover valid, empty, and corrupt streams and error propagation.
Object and tree read tests
__tests__/test-readObject*.js, __tests__/test-readTree*.js
Tests check decompression errors when object and tree reads encounter corrupt compressed data, including submodule reads. deflated object reads return the supplied bytes.

Contributor Credit

Layer / File(s) Summary
Contributor records
.all-contributorsrc, README.md
The contributor configuration and README add snowyukitty with code and test contributions.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Suggested reviewers: jcubic


Merge Risk: ⚪ Minimal · up to e5b40

No actionable issue remains from this review. The change is mergeable after normal checks.

Security Architecture Review

Security architecture risk: ⚪ Minimal · up to 1050c

The change preserves decompression diagnostics without expanding repository access, privileges, or accepted input. Existing error serialization and object-integrity checks remain unchanged. No material security risk was found introduced or worsened by this change.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — A party able to corrupt bytes in a repository's loose-object store can trigger rejection through the existing decompression path. This change alters the rejected diagnostic payload, not the repository selection, filesystem authority, or compressed-input reachability.

Trust Boundaries and Controls

  • observed — The existing distinction between raw compressed passthrough, wrapped data, and hash-checked content remains intact. Error normalization neither accepts corrupt compressed data nor removes the content-read hash check.

Resilience and Maintainability Implications

  • observed — The loose reader creates a per-call result object. If inflation rejects, execution stops before replacing its object or changing its format. The changed failure path introduces no persistent write or shared-state transition requiring rollback or recovery.

Pre-merge checks | Passed 4 | Failed 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 14 files. (2 skipped: 2… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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 describes the main change: preserving Pako decompression errors while reading objects.

Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 14 files. (2 skipped: 2 unsupported.)


✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

  • Autopilot · 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

A rabbit checks the bytes with care
A stream comes back from frosty air
When headers fail, the errors speak
The tests explore each snowy peak
A new name joins the credits page
Then hops away, content in gauge

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

@jcubic

jcubic commented Oct 6, 2026

Copy link
Copy Markdown
Member

There is a conflict with the list of contributors. Can you resolve it?

Comment thread src/utils/inflate.js Resolved
Comment thread src/utils/inflate.js Resolved
@snowyukitty

Copy link
Copy Markdown
Contributor Author

Addressed both review findings in d899055.

  • Corrupt Pako input now produces a plain Error with the decompression diagnostic, without InternalError's library-bug guidance. The readObject/readTree regressions also check caller attachment in regular repositories and submodules.
  • The native path is awaited inside the try block. browserInflate handles asynchronous empty TypeError failures with a nonempty invalid-buffer message and preserves informative Error instances. Native-backend activation remains unchanged.

On Node 22 and Node 24, lint, Rollup, declarations, native JavaScript typecheck and all ten focused suites passed (87 tests and 36 snapshots on each runtime). A contained Chromium smoke test round-tripped binary input and rejected three corrupt streams with nonempty diagnostics. This is focused validation, not a full-suite pass.

The prior contributor-list conflict resolution is retained, and the PR description now reflects the error behavior and current validation.

Comment thread src/utils/inflate.js Resolved
Comment thread src/utils/inflate.js Resolved
@snowyukitty

Copy link
Copy Markdown
Contributor Author

Addressed the error-hierarchy and native-error comments in e5b405d:

  • Added Errors.DecompressionError, a BaseError subclass, for Pako string failures. Its diagnostic, code, data and serialization are covered by regression tests.
  • The native path is awaited; asynchronous empty TypeError failures in browserInflate now use the same error type with a nonempty diagnostic. Informative errors retain their identity, and native-backend activation stays unchanged.
  • Merged current main and regenerated the contributor table, preserving every upstream contributor.

On this head, Node 22 and 24 each passed lint, Rollup, declarations, JavaScript typechecking and ten focused suites (89 tests, 36 snapshots). The classification regressions fail against the previously published inflation helpers. Chromium smoke checks passed for valid binary data, three corrupt streams and an asynchronous empty native error. The full Node/Chrome suite was not run for this revision.

Comment thread src/utils/browserInflate.js Resolved
Comment thread src/utils/inflate.js Resolved
@snowyukitty

Copy link
Copy Markdown
Contributor Author

Renamed the shared helper, module and focused test to nativeInflate in d767f69.

I also reproduced your exact [0, 0] example on Node 22 and 24: DecompressionStream throws a TypeError with an empty message, and nativeInflate reports DecompressionError with Invalid compressed buffer: decompression failed.

On this head, both Node versions passed lint, Rollup, declarations, JavaScript typechecking and ten focused suites (89 tests, 36 snapshots each). Chromium smoke checks passed for valid binary data, three corrupt streams and an asynchronous empty native error. The full Node/Chrome suite was not run for this revision.

Comment thread .all-contributorsrc Resolved
@jcubic

jcubic commented Oct 10, 2026

Copy link
Copy Markdown
Member

I also reproduced your exact [0, 0] example on Node 22 and 24: DecompressionStream throws a TypeError with an empty message, and nativeInflate reports DecompressionError with Invalid compressed buffer: decompression failed.

So could you fix the code?

Restore literal Unicode contributor names without changing parsed metadata. Reproduce the raw [0, 0] platform error beside nativeInflate and verify the diagnostic, classification, and serialized data.
@snowyukitty

Copy link
Copy Markdown
Contributor Author

I've restored the literal Unicode names in .all-contributorsrc; escaping them was an unnecessary formatting change. The parsed contributor data is unchanged, and regenerating the table leaves README.md unchanged.

For [0, 0], the library-side fix is in nativeInflate: it awaits the stream read inside try and converts an empty native TypeError to DecompressionError with the diagnostic decompression failed. The direct platform example still throws the native error; calling the helper on Node 22 and 24 returns DecompressionError with a nonempty message and serialized diagnostic.

c0b935f adds a regression using your actual input, checking the raw failure beside the helper's diagnostic, classification and serialized data. Informative native errors retain their name and message. The updated branch passed lint, build and typechecking, plus 11 focused suites (97 tests and 36 snapshots on each of Node 22 and 24). The full Node/browser suites and a Chromium smoke test were not run for this revision.

@jcubic
jcubic merged commit b75230a into isomorphic-git:main Oct 12, 2026
4 checks passed
@jcubic

jcubic commented Oct 12, 2026

Copy link
Copy Markdown
Member

🎉 This PR is included in version 1.44.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

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