fix: detect OAuth token expiry and show actionable error message#371
fix: detect OAuth token expiry and show actionable error message#371YunshuGao wants to merge 1 commit into
Conversation
Previously, when the Claude API returned a 401 authentication_error (e.g. "OAuth token has expired"), the plugin did not recognise it as a specific error type. It fell through to generic error handling, showing a raw JSON API error that was confusing and unhelpful. Changes: - Add isAuthenticationError() in session.ts with patterns for OAuth expiry, invalid API key, and 401 authentication errors - Catch auth errors early in ClaudianService.ts before session-retry logic (retrying with an expired token is pointless) - Show clear message: "run claude auth login to re-authenticate" - Fire an Obsidian Notice toast so the error is visible Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
YishenTu
left a comment
There was a problem hiding this comment.
Code Review
The approach is sound — intercepting authentication errors before session-retry logic makes sense since retrying with expired credentials is pointless. The detection function follows the same pattern as isSessionExpiredError, which is good. A few issues to address:
Must fix
-
No tests —
isAuthenticationError()has zero unit tests despite the project's TDD mandate and an existing test suite for the sister functionisSessionExpiredErrorintests/unit/utils/session.test.ts. -
Overly broad compound pattern —
{ includes: ['token', 'expired'] }insession.tsoverlaps with session-expired patterns. An error like"session token has expired"would be caught as a non-recoverable auth error instead of a recoverable session error, sinceisAuthenticationErroris checked first at every call site. Should be narrowed (e.g., require'oauth'too) or removed since'oauth token has expired'already matches the simple pattern list.
Should fix
-
6× duplicated error message strings — The long error message and Notice text are copy-pasted across
ClaudianService.ts. Extract to constants to prevent drift and simplify future wording changes. -
Inconsistent
closePersistentQuery— The persistent query path callsclosePersistentQuery('authentication error')on auth errors, but the crash recovery path instartPersistentQueryConsumerdoesn't. After a failedensureReady()with auth error, the persistent query may be in a half-initialized state.
Nit
- String handling inconsistency —
isAuthenticationErrorhandlestypeof error === 'string'but the adjacentisSessionExpiredErroronly handlesErrorinstances. Worth aligning or documenting why they differ.
Summary
isAuthenticationError()detection for OAuth token expiry, invalid API key, and 401 authentication errorsClaudianService.tsbefore session-retry logic (retrying with an expired token is pointless)claude auth loginto re-authenticate" instead of raw API JSONNoticetoast (10s) so the error is visible to usersProblem
When the Claude API returns a 401
authentication_error(e.g. "OAuth token has expired"), the plugin doesn't recognise it as a specific error type. It falls through to generic error handling, showing a raw JSON API error like:This is confusing and gives users no guidance on how to fix it.
Root Cause
isSessionExpiredError()insession.tsonly matches patterns like "session expired" / "session not found". OAuth/authentication errors don't match any of those patterns.Test plan