medusajs/medusa · error · AuthCallbackError
resolveProvisionError(error, t)
Error message
resolveProvisionError(error, t)
What it means
When a user authenticates via SSO in the admin dashboard, a JWT token is exchanged and then used to provision (find or create) the local admin user. If the provisioning step (ensureUser) fails for any reason — expired token, missing invite, invalid role, or a backend rejection — the raw error is passed through resolveProvisionError(error, t) which maps it to a translated, user-friendly message and rethrows it as an AuthCallbackError to be shown as a toast on the login screen.
Source
Thrown at packages/admin/dashboard/src/routes/login/components/sso-login.tsx:235
navigate("/login")
}
})
return
}
if (typeof result === "object" && "verification_required" in result) {
throw new Error("Verification required but not implemented yet")
}
token = result
} catch (error) {
throw new AuthCallbackError(t("auth.login.authenticationFailed"))
}
try {
await ensureUser(token)
} catch (error) {
throw new AuthCallbackError(resolveProvisionError(error, t))
}
navigate("/")
} catch (error) {
toast.error(
error instanceof AuthCallbackError
? error.message
: t("auth.login.authenticationFailed")
)
// Navigate to /login without the query string, otherwise a failed
// callback would get stuck on the spinner. There's no point in keeping the
// query string anyway because the callback would just fail again.
navigate("/login")
}
setIsPending(false)
}, [providerId, searchParams, t, onMfaChallenge, ensureUser, navigate])
View on GitHub (pinned to 5e06e544a2)
Solutions
- Check the browser network tab for the failing request following the token exchange (typically a call to /auth/user/me or the user create endpoint) and read its response body for the underlying cause
- If the user does not yet exist in Medusa, create an invite (POST /admin/invites) and have the user log in again, or provision the user via the provider first
- Verify the auth provider configuration (client ID, secret, redirect/callback URL) in medusa-config and that the token is still valid when the callback fires
- Retry the login from the sign-in screen; if it persists, inspect server logs for the exception thrown by ensureUser
Example fix
// before
try {
await ensureUser(token)
} catch (error) {
throw new AuthCallbackError(resolveProvisionError(error, t))
}
// after (ensure the user is invited/provisioned first)
// POST /admin/invites { email: "user@example.com", role: "member" }
// then retry the SSO login so ensureUser(token) succeeds Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
null
Try / catch
try {
await handleCallback()
} catch (error) {
if (error instanceof AuthCallbackError) {
// already translated user-facing message from resolveProvisionError
toast.error(error.message)
} else {
toast.error("Unexpected error during SSO login")
console.error(error)
}
} Prevention
- Ensure admin users are invited (POST /admin/invites) before their first SSO login
- Keep the auth provider's client ID/secret and callback URL in sync with medusa-config
- Handle the callback promptly so provider tokens don't expire mid-flow
When it happens
Trigger: Completing an SSO/OIDC callback in the admin dashboard where the auth provider returns a token but the subsequent ensureUser(token) call fails: e.g. the token is rejected by the /auth/user/me or user-creation endpoint, the user is not invited/created in Medusa, or the provider token lacks required claims.
Common situations: First-time SSO login before an admin invite has been accepted; the identity provider's token expired between redirect and callback; misconfigured auth provider (wrong client id/secret/redirect URI); a user authenticates successfully upstream but is not provisioned as an admin user in Medusa.
Related errors
AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27).
Data as JSON: /api/errors/bd9a1749ecc54df1.
Report an issue: GitHub.