nextauthjs/next-auth · error · OAuthCallbackError
OAuth Provider returned an error
Error message
OAuth Provider returned an error
What it means
When validating the OAuth redirect response, openid-client may raise AuthorizationResponseError (e.g. the provider redirected back with error=access_denied, a missing/mismatched state, or an invalid code). Auth.js catches it inside handleOAuth and rethrows it as OAuthCallbackError('OAuth Provider returned an error') with the provider id and response error entries as the cause.
Source
Thrown at packages/core/src/lib/actions/callback/oauth/callback.ts:147
const state = await checks.state.use(cookies, resCookies, options)
let codeGrantParams: URLSearchParams
try {
codeGrantParams = o.validateAuthResponse(
as,
client,
new URLSearchParams(params),
provider.checks.includes("state") ? state : o.skipStateCheck
)
} catch (err) {
if (err instanceof o.AuthorizationResponseError) {
const cause = {
providerId: provider.id,
...Object.fromEntries(err.cause.entries()),
}
logger.debug("OAuthCallbackError", cause)
throw new OAuthCallbackError("OAuth Provider returned an error", cause)
}
throw err
}
const codeVerifier = await checks.pkce.use(cookies, resCookies, options)
let redirect_uri = provider.callbackUrl
if (!options.isOnRedirectProxy && provider.redirectProxyUrl) {
redirect_uri = provider.redirectProxyUrl
}
let codeGrantResponse = await o.authorizationCodeGrantRequest(
as,
client,
clientAuth,
codeGrantParams,
redirect_uri,
codeVerifier ?? "decoy",View on GitHub (pinned to a1a16a5a77)
Solutions
- Inspect the OAuthCallbackError cause (entries like error, error_description, state) to read the provider's actual rejection reason
- If error=access_denied, the user declined consent — handle it gracefully in the UI, no code change needed
- Fix cookie/state issues: ensure NEXTAUTH_URL/AUTH_URL matches the origin, cookies are not blocked, and the auth secret is stable across instances
- Re-authorize the app / request provider approval scopes if the provider rejects unregistered redirect URIs or unapproved apps
Example fix
// before
// no error handling: user sees raw failure after canceling consent
// after
try {
await signIn("github")
} catch (e) {
if (e instanceof OAuthCallbackError) {
// e.cause.error === "access_denied" etc.
showToast("Sign-in was canceled or rejected by the provider")
}
} Defensive patterns
Strategy: try-catch
Validate before calling
// before redirecting to the provider, confirm callback URL and cookies are sane
if (!window.cookiesEnabled) console.warn("State cookie may be dropped; sign-in can fail") Type guard
function isOAuthCallbackError(e: unknown): e is OAuthCallbackError {
return e instanceof OAuthCallbackError
} Try / catch
try {
await signIn(providerId)
} catch (e) {
if (isOAuthCallbackError(e)) {
const { error, error_description } = e.cause ?? {}
// access_denied, invalid_state, etc. — surface to user or log
}
} Prevention
- Keep NEXTAUTH_URL/AUTH_URL and the auth secret consistent across environments and instances
- Avoid multiple concurrent sign-in tabs that overwrite state cookies
- Pre-register exact callback URLs with the OAuth provider
- Test consent-cancellation flows and surface friendly messages for access_denied
When it happens
Trigger: The provider redirects to the callback URL with an error parameter (user denied consent, app not approved); the state/PKCE cookie is missing or mismatched (blocked cookies, cross-domain redirect, multiple tabs); the authorization code is invalid, expired, or already redeemed.
Common situations: User cancels the consent screen at the provider; NEXTAUTH_URL/auth secret mismatch across environments causing state cookie decryption failures; multiple sign-in tabs overwriting state cookies; mobile in-app browsers stripping cookies; provider app in development mode rejecting unregistered testers.
Related errors
- OAuth Provider returned an error: ${responseJson.error}
- Missing or invalid provider account
- Provider not supported
- State data was provided but the provider is not configured t
- Invalid state
AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28).
Data as JSON: /api/errors/fea827929a8b2fcf.
Report an issue: GitHub.