Skip to content

Preserve $previous chain in exception wraps#35

Merged
turegjorup merged 1 commit into
developfrom
fix/exception-cause-chain
May 11, 2026
Merged

Preserve $previous chain in exception wraps#35
turegjorup merged 1 commit into
developfrom
fix/exception-cause-chain

Conversation

@turegjorup
Copy link
Copy Markdown
Contributor

Summary

Five sites in the bundle catch an upstream exception and rethrow as a bundle exception with the message copied — but the chain to the originating exception is dropped. This means error logs (and $e->getPrevious() traversal) lose the underlying PSR cache or upstream OIDC failure, making debug from a 500/503 response impossible to root-cause without reading the bundle source.

Fixed by adding previous: $e (named argument) to each new CacheException(...) / new ValidationException(...). No public API change; concrete exception types and messages are unchanged.

Sites fixed

File Site Caught Rethrown
src/Util/CliLoginHelper.php createToken first getItem PSR cache InvalidArgumentException CacheException
src/Util/CliLoginHelper.php createToken second getItem PSR cache InvalidArgumentException CacheException
src/Util/CliLoginHelper.php getUsername getItem PSR cache InvalidArgumentException CacheException
src/Util/CliLoginHelper.php getUsername deleteItem PSR cache InvalidArgumentException CacheException
src/Security/OpenIdLoginAuthenticator.php validateClaims token validation ItkOpenIdConnectException ValidationException

Tests

Converted the five existing expectException + expectExceptionMessage tests to a try/catch/early-return pattern so each test now also asserts getPrevious() returns the original cause object (same pattern as PR #33). Test count (56) and coverage (100%) unchanged.

Backward compatibility

Additive only. Consumers reading $e->getMessage() or catching the concrete exception types still behave the same. Consumers reading $e->getPrevious() now get the cause they previously got null for — a strict improvement.

Test plan

  • task test — 56 tests, 141 assertions pass
  • task analyze:php — phpstan max, no errors
  • task lint:php — clean
  • task test:matrix — pending in CI

Context

Part of the larger exception-contract migration described in EXCEPTION-CONTRACT-MIGRATION.md (PR 0). Self-contained patch-level fix; does not depend on the upcoming 5.0 contract work.

🤖 Generated with Claude Code

Five wrap sites (4 in CliLoginHelper, 1 in OpenIdLoginAuthenticator::validateClaims) copied the message from the caught exception but discarded the chain. Logs lost the originating PSR cache / upstream OIDC failure, making debug traversal impossible. Add `previous: $e` to each `new CacheException(...)` / `new ValidationException(...)`.

Test changes: convert the existing message-only assertions to a try/catch + early-return pattern so each test also asserts `getPrevious()` returns the original cause object. Five existing tests touched; test count and coverage unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@turegjorup turegjorup self-assigned this May 11, 2026
@codecov-commenter
Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (53c62a5) to head (3b6152b).

Additional details and impacted files
@@             Coverage Diff             @@
##             develop       #35   +/-   ##
===========================================
  Coverage     100.00%   100.00%           
  Complexity        60        60           
===========================================
  Files              9         9           
  Lines            278       278           
===========================================
  Hits             278       278           
Flag Coverage Δ
unittests 100.00% <100.00%> (ø)

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.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

turegjorup added a commit that referenced this pull request May 11, 2026
Records the decision to migrate the bundle (and upstream library) to a marker-interface exception contract: cross-package marker interfaces, concretes extending SPL types, wrap-at-boundary discipline with `$previous` chained, and the controller HTTP-exception exit treated as a documented carve-out. Migration via coordinated 5.0 majors across `itk-dev/openid-connect` and this bundle, sequenced as four PRs. PR 0 (cause-chain bug fixes) already in flight as PR #35.

The ADR is self-contained: context, drivers, three options considered, decision, consequences, and references (PSR-18, Symfony's component markers and Psr18Client, Bloch's wrap-at-boundary principle).

Status: Draft — awaits team review.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@turegjorup turegjorup requested a review from jekuaitk May 11, 2026 10:58
@turegjorup turegjorup merged commit c65ff56 into develop May 11, 2026
15 checks passed
@turegjorup turegjorup deleted the fix/exception-cause-chain branch May 11, 2026 11:45
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.

3 participants