Skip to content

fix: harden catch blocks against non-Error throws (#142, #147) - #154

Merged
heskew merged 2 commits into
mainfrom
fix/142-147-harden-catch-nonerror
Jul 1, 2026
Merged

heskew merged 2 commits into
mainfrom
fix/142-147-harden-catch-nonerror

Conversation

@heskew

@heskew heskew commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

(error as Error).message in a catch (error) block crashes the catch itself when a non-Error value is thrown — (null).message throws TypeError, defeating the "swallow and log" contract. This is a comprehensive sweep of all remaining occurrences after #141 fixed hookManager.ts, token.ts, and withMCPAuth.ts.

All 16 remaining sites replaced with error instanceof Error ? error.message : String(error).

Every catch site changed

File Location Context
src/index.ts :313 session validator provider resolution
src/lib/sessionValidator.ts :97 token validation error log
src/lib/sessionValidator.ts :181 token refresh error log
src/lib/sessionValidator.ts :186 Token refresh failed: error string
src/lib/resource.ts :381 dynamic provider resolution
src/lib/OAuthProvider.ts :161 additional user info fetch fallback
src/lib/OAuthProvider.ts :225–226 ID token signature verification log + rethrow message
src/lib/handlers.ts :239 ID token verification fallback log
src/lib/handlers.ts :332 OAuth callback error reason derivation
src/lib/providers/github.ts :42 GitHub token validation error
src/lib/providers/github.ts :76 GitHub email fetch failure
src/lib/mcp/dcr.ts :296 client registration storage failure
src/lib/mcp/wellKnown.ts :273 well-known handler failure
src/lib/mcp/authorize.ts :203 client lookup failure
src/lib/mcp/authorize.ts :292 CSRF token generation failure
src/lib/mcp/callback.ts :93 auth code persistence failure

Tests

Added 4 non-Error throw cases to test/lib/hookManager.test.js for callOnLogin (string throw + null throw), callOnLogout (null throw), and callOnTokenRefresh (string throw) — these are the async-await hook methods directly exercisable without a DB. The mcp store catch sites (dcr/authorize/callback/wellKnown) wrap DB calls that are not trivially mockable; those changes are mechanical and compiler-verified.

Closes #142
Closes #147

🤖 Generated with Claude Code — Claude Sonnet 4.6

Replace every remaining (error as Error).message inside catch blocks with
error instanceof Error ? error.message : String(error). When a non-Error
value (null, string, number) is thrown, the cast form crashes the catch
itself — (null).message throws TypeError — defeating the catch's
swallow-and-log contract.

#141 already fixed hookManager.ts (callOnLogin/Logout/TokenRefresh/
callResolveProvider/callOnMCPTokenIssued) and token.ts / withMCPAuth.ts.

This sweep fixes all remaining sites found by exhaustive grep:

  src/index.ts:313                       — session validator provider resolution
  src/lib/sessionValidator.ts:97         — token validation error log
  src/lib/sessionValidator.ts:181        — token refresh error log
  src/lib/sessionValidator.ts:186        — Token refresh failed: error message
  src/lib/resource.ts:381                — dynamic provider resolution
  src/lib/OAuthProvider.ts:161           — additional user info fetch fallback
  src/lib/OAuthProvider.ts:225-226       — ID token signature verification log + rethrow
  src/lib/handlers.ts:239               — ID token verification fallback log
  src/lib/handlers.ts:332               — OAuth callback error reason derivation
  src/lib/providers/github.ts:42        — GitHub token validation error
  src/lib/providers/github.ts:76        — GitHub email fetch failure
  src/lib/mcp/dcr.ts:296               — client registration storage failure
  src/lib/mcp/wellKnown.ts:273          — well-known handler failure
  src/lib/mcp/authorize.ts:203          — client lookup failure
  src/lib/mcp/authorize.ts:292          — CSRF token generation failure
  src/lib/mcp/callback.ts:93            — auth code persistence failure

Tests: add 4 non-Error throw assertions in hookManager.test.js for
callOnLogin (string + null), callOnLogout (null), and callOnTokenRefresh
(string) — the async-await methods that are easily exercised without DB
mocking. The mcp store catches (dcr/authorize/callback/wellKnown) are
mechanical compiler-verified changes over DB-wrapping code.

Closes #142
Closes #147

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@heskew
heskew requested a review from kriszyp July 1, 2026 19:20

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request improves error handling safety across the codebase by replacing unsafe type assertions on caught errors with explicit instanceof Error checks, and adds unit tests to verify behavior when non-Error values are thrown. The reviewer feedback is highly constructive, recommending that raw error objects be passed directly to loggers to preserve stack traces and metadata, and suggesting the use of the cause option when wrapping and re-throwing errors to maintain the original error context.

Comment thread src/index.ts
Comment thread src/lib/OAuthProvider.ts
Comment thread src/lib/OAuthProvider.ts Outdated
Comment thread src/lib/handlers.ts
Comment thread src/lib/sessionValidator.ts
Comment thread src/lib/sessionValidator.ts
@claude

claude Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Reviewed; no blockers found.

@github-actions

github-actions Bot commented Jul 1, 2026 •

Copy link
Copy Markdown
Contributor

Reviewed; no blockers found.

The PR correctly hardens error handling across the plugin by replacing unsafe (error as Error).message casts with robust error instanceof Error ? error.message : String(error) guards. This prevents potential secondary crashes when logging or reporting errors that are not Error instances (e.g., strings or nullish values thrown from custom hooks). The addition of cause: error to re-thrown verification errors is a valuable improvement for debugging.

The new unit tests for HookManager successfully verify that the lifecycle hooks safely handle non-Error throws without breaking the main authentication flow.

Comment thread src/lib/OAuthProvider.ts Outdated
Comment thread src/lib/sessionValidator.ts
Gemini review on #154: preserve the original error via Error cause when
wrapping the ID-token verification failure, per HEG error-handling
(cause chaining). Log sites keep the safe message ternary for
consistency with the #141 convention.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@heskew
heskew marked this pull request as ready for review July 1, 2026 19:31
@heskew
heskew merged commit 2ab8f6c into main Jul 1, 2026
26 checks passed
@heskew
heskew deleted the fix/142-147-harden-catch-nonerror branch July 1, 2026 19:31
@heskew heskew mentioned this pull request Jul 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant