anomalyco/sst · error · OauthError
error
Error message
error
What it means
In the OAuth adapter's form_post callback route, if the identity provider POSTs an `error` field in the form body, the adapter rethrows it as an `OauthError`. This surfaces provider-side OAuth failures (per RFC 6749) such as `access_denied`, `invalid_request`, or `server_error` back to your handler with the raw provider error code as the message.
Source
Thrown at sdk/js/src/auth/adapter/oauth.ts:103
config.issuer.metadata.userinfo_endpoint
? "callback"
: "oauthCallback"
](callback.toString(), query, {
code_verifier,
state,
});
return ctx.success(c, {
client,
tokenset,
});
});
// response_mode=form_post
routes.post("/callback", async (c) => {
const [callback, client] = getClient(c);
const form = await c.req.formData();
if (form.get("error")) {
throw new OauthError(form.get("error")!.toString());
}
const code_verifier = getCookie(c, "auth_code_verifier");
const state = getCookie(c, "auth_state");
const tokenset = await client[
config.issuer.metadata.userinfo_endpoint
? "callback"
: "oauthCallback"
](callback.toString(), Object.fromEntries(form as any), {
code_verifier,
state,
});
return ctx.success(c, {
client,
tokenset,
});
});
} satisfies Adapter<{
tokenset: TokenSet;View on GitHub (pinned to a0bd20f762)
Solutions
- Read `error.response`/the OauthError message to identify the provider error code and handle it (e.g. show a 'consent denied' UI for access_denied).
- Verify your OAuth client config: client ID, secret, redirect URI, and requested scopes match the provider's registered values.
- Restart the login flow from /authorize — OAuth errors on callback are not retryable with the same request.
- Check the provider dashboard/logs for the corresponding authorization failure detail.
Example fix
try {
await client.auth.<provider>.authorize(...)
} catch (e) {
if (e instanceof OauthError && e.message === "access_denied") {
return new Response("You must grant access to continue", { status: 403 });
}
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
// Check before redirecting to the IdP that client config is registered correctly
const redirect = await client.authorizationUrl({ redirect_uri, scope });
if (!redirect) throw new Error("OAuth client not configured"); Type guard
function isOauthError(e: unknown): e is OauthError {
return e instanceof OauthError;
} Try / catch
try {
await completeLogin(c);
} catch (e) {
if (e instanceof OauthError) {
if (e.message === "access_denied") return c.text("Access denied by user", 403);
return c.text("OAuth error: " + e.message, 502);
}
throw e;
} Prevention
- Always wrap OAuth callback handling in try/catch — provider errors are expected user behavior.
- Register redirect URIs, scopes, and grant types exactly as requested in the provider dashboard.
- Map provider error codes (access_denied, invalid_request) to user-friendly messages.
When it happens
Trigger: An IdP POSTs to `/<auth-name>/callback` (response_mode=form_post) with `error` in the form body instead of `code`/`state`. Happens when the user denies consent, the authorization request was malformed, scopes are invalid, or the provider errors out during authorization.
Common situations: User cancels the consent screen (`access_denied`); misconfigured redirect URI or client ID (`invalid_request`, `unauthorized_client`); requesting scopes the app isn't approved for; IdP outage (`temporarily_unavailable`); expired or replayed authorization flow.
Related errors
- Missing token parameter
- Unsupported response_type: ${response_type}
- Invalid grant_type
- Missing code
- redirect_uri mismatch
AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30).
Data as JSON: /api/errors/ba4c8d9c9b15b6c3.
Report an issue: GitHub.