Skip to content

fix: keep erased errors visible to source-iteration and downcasting#2702

Merged
Sebastian Thiel (Byron) merged 4 commits into
GitoxideLabs:mainfrom
ameyypawar:fix/2694-exn-source-chain
Jul 9, 2026
Merged

fix: keep erased errors visible to source-iteration and downcasting#2702
Sebastian Thiel (Byron) merged 4 commits into
GitoxideLabs:mainfrom
ameyypawar:fix/2694-exn-source-chain

Conversation

@ameyypawar

Copy link
Copy Markdown
Contributor

Fixes #2694.

The problem

gix diff file treats a revspec that fails to resolve as a path on disk, by walking the failed rev-parse's sources() and downcasting each error to find the ref-not-found error. Since 499402c (found by Christoph Rüßler (@cruessler)'s bisect in #2694), Exn::erased() wraps the original error in the Untyped marker so that the typed accessors of Exn<Untyped> keep working — but the marker also hid the original error from everything that walks the error afterwards:

  • frames now yielded the marker, which cannot be downcast to the original error type, and
  • Untyped's empty Error implementation returned None for source(), cutting off the chain below it.

That made the revspec→path fallback unreachable, so gix diff file :README.md README.md failed with Error: couldn't parse revision: "README.md".

The fix

Frame::error() now unwraps the erasure marker to return the original error, downcast_any_ref() goes through it, and Untyped forwards source(). Erasure thus no longer affects how errors are discovered, while the typed accessors (Exn::error(), into_inner(), into_box()) keep seeing Untyped as their compile-time type, just like 499402c intended — its tests for that are untouched and keep passing.

Two new unit tests pin this down, one of them mirroring the exact sources()-downcast pattern that broke.

Journey test

The regression could go unnoticed because gix diff file had no journey-test coverage, so this adds the missing test: it diffs an index revspec (:b) against the file on disk and snapshots the resulting hunk. Without the fix it fails with the exact error from #2694.

…itoxideLabs#2694)

Since 499402c, erasing an Exn wraps its error in the Untyped marker so that
the typed accessors of Exn<Untyped> keep working. However, the marker also hid
the original error from everything that walks the error afterwards: frames now
yielded the marker, which cannot be downcast to the original type, and whose
empty Error implementation cut off the source chain below it.

This broke gix diff file, whose fallback for treating a revspec as a path on
disk downcasts the sources() of a failed rev-parse to find the ref-not-found
error - it would now fail with "couldn't parse revision" instead.

Frame::error() now unwraps the erasure marker to return the original error,
downcast_any_ref() goes through it, and Untyped forwards source(), so erasure
no longer affects how errors are discovered - while the typed accessors keep
seeing Untyped as their compile-time type, just like before.

Also adds the previously missing journey-test coverage for gix diff file.
@Byron
Sebastian Thiel (Byron) marked this pull request as ready for review July 9, 2026 12:59
- add an additional `gix` based test to not rely on journey tests for development tools

Co-authored-by: GPT 5.5 <[email protected]>
@Byron
Sebastian Thiel (Byron) merged commit e9c973d into GitoxideLabs:main Jul 9, 2026
32 checks passed
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.

gix diff file :README.md README.md fails with Error: couldn't parse revision: "README.md"

2 participants