Skip to content

fix(oauth): surface server error detail from finishOAuthLogin#83

Merged
Bccorb merged 1 commit into
mainfrom
fix/oauth-error-detail
Jul 20, 2026
Merged

fix(oauth): surface server error detail from finishOAuthLogin#83
Bccorb merged 1 commit into
mainfrom
fix/oauth-error-detail

Conversation

@Bccorb

@Bccorb Bccorb commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

What

finishOAuthLogin() now throws a SeamlessAuthError carrying the auth server's message, HTTP status, and parsed body, instead of discarding the response and throwing a generic Error('Failed to finish OAuth login').

SeamlessAuthError is exported from src/index.ts so callers can narrow with instanceof and read status and body.

Closes #51.

Important: this does not fully deliver the issue's motivating case

The issue's motivation is the "provider did not return an email address" failure. That specific reason is not currently exposed by the API, so this change alone will not make it actionable.

In seamless-auth-api, the OAuth callback's catch block logs the reason server-side (metadata: { reason: 'callback_failed' }) and responds with a generic { error: 'OAuth login failed' }. There is no distinct payload or code for the missing-email case, so that is the most detail the SDK can surface today.

What this PR does deliver: every reason the API does distinguish now reaches the caller, for example OAuth signup is disabled (403), Invalid OAuth state (400), and OAuth provider not found (404).

Making the missing-email case actionable needs a follow-up in seamless-auth-api to return a distinct error (ideally with a stable machine-readable code). Worth filing there.

Correction to the issue's proposed fix

The description proposes reading res.error?.message and res.error?.code from the server-side @seamless-auth/core result shape. Two mismatches with this repo:

  • The React client returns a raw Response, not { ok, error, status }, so the body has to be read explicitly and defensively (it may be empty or non-JSON).
  • The API reports failures as { error: string }. There is no message field and no code field, so a code cannot be populated yet. message is still accepted as a fallback shape in case other endpoints differ.

Relationship to #24

This defines an error convention, which is #24's job. I kept the surface deliberately small (one error class, no result-object refactor) so #24 can supersede or extend it without a second migration. Noted on both issues.

Tests

  • tests/errors.test.ts: message extraction from error, fallback to message, fallback when the body is not JSON, fallback on an empty message, and instanceof Error with a stable name.
  • tests/authProvider.test.tsx: provider-level cases asserting the server detail reaches the caller and that a non-JSON body falls back cleanly.

Confirmed the provider tests actually catch the regression: with the fix reverted they fail with the old [Error: Failed to finish OAuth login].

errors.ts is at 100% coverage.

Checks

  • npm run typecheck, npm run lint, npm run format:check clean
  • Full suite: 188 passed (7 new)
  • Changeset (minor): new public export, and the thrown error message changes for callers matching on the old string

@Bccorb
Bccorb merged commit 0a37241 into main Jul 20, 2026
2 of 3 checks passed
@Bccorb
Bccorb deleted the fix/oauth-error-detail branch July 20, 2026 01:28
@Bccorb

Bccorb commented Jul 20, 2026

Copy link
Copy Markdown
Contributor Author

Filed the API-side follow-up: fells-code/seamless-auth-api#91.

That ticket covers returning a stable machine-readable code for the failures the API currently collapses into the generic OAuth login failed, including the missing-email case that motivated #51. The detail already exists server-side (fetchOAuthProfile throws 'OAuth profile did not include an email address') and is discarded by the controller's catch-all.

Once that lands, consumers can read body.code off the SeamlessAuthError this PR introduces and map oauth_missing_email to their own messaging. No change needed here to support it.

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.

finishOAuthLogin swallows server error detail, throws generic Error

1 participant