Skip to main content

Auth Error Codes

Beta

This feature is in beta. Core behavior is stable, but some APIs or configuration may change before general availability.

Complete reference for all authentication error codes returned by EdgeBase.

Error Response Format

All authentication errors return a consistent JSON structure:

{
"code": 401,
"message": "Invalid credentials.",
"slug": "invalid-credentials",
"data": {}
}
FieldTypeDescription
codenumberHTTP status code (400, 401, 403, 404, 409, 429, 500, 503)
messagestringHuman-readable description of the error
slugstring(Optional) Semantic error identifier for programmatic handling (e.g., invalid-credentials)
dataobject(Optional) Additional context (e.g., { "captcha_required": true })
Auth middleware 401 responses

Auth middleware responses (token expired, invalid token, auth not configured) return an error field instead of slug. For example: { "error": "Token expired" }. When handling 401 errors, check for the error field in addition to slug.

Use slug for programmatic error handling

The slug field provides a stable, machine-readable identifier for each error type. Unlike message (which may change across versions or locales), slug values are part of the public API contract and safe to match on in application code. See the SDK Error Handling section for examples.


Sign Up Errors

StatusSlugMessageWhenHandling
400invalid-inputEmail and password are required.Missing email or password field in request bodyShow form validation — highlight empty fields
400invalid-emailInvalid email format...Email fails format validationShow email-specific validation message
400password-too-shortPassword must be at least 8 characters.Password shorter than 8 charactersShow password requirements hint
409email-already-existsEmail already registered.An account with this email already existsSuggest signing in or resetting password
429rate-limitedToo many signup attempts...Signup rate limit exceededShow retry timer with countdown
403hook-rejectedAuth hook 'beforeSignUp' rejected the operation.beforeSignUp hook returned a rejectionDisplay hook's custom message if provided

Sign In Errors

StatusSlugMessageWhenHandling
400invalid-inputEmail and password are required.Missing email or password fieldShow form validation
401invalid-credentialsInvalid credentials.Wrong email or wrong passwordShow generic error — do not reveal which field is incorrect
403oauth-onlyThis account uses OAuth sign-in. Password login is not available.User registered via OAuth, not email/passwordRedirect user to the appropriate OAuth provider
403hook-rejectedAuth hook 'beforeSignIn' rejected the operation.beforeSignIn hook returned a rejectionDisplay hook's custom message if provided
429rate-limitedToo many login attempts...Sign-in rate limit exceeded (per email)Show retry timer with countdown

OAuth Errors

StatusSlugMessageWhenHandling
400validation-failedUnsupported OAuth provider: {provider}Provider name not recognizedCheck provider name spelling
400feature-not-enabledOAuth provider {provider} is not enabled.Provider not listed in allowedOAuthProviders configEnable provider in server config
500internal-errorOAuth provider {provider} is not configured.Missing clientId or clientSecret env varsSet required environment variables
400validation-failedOAuth error: {description}OAuth provider returned an error in callbackDisplay the provider's error description
400validation-failedMissing code or state parameter.Callback URL missing required query paramsRestart the OAuth flow
400invalid-tokenInvalid or expired OAuth state.State token expired (5 min TTL) or CSRF mismatchRestart the OAuth flow
400validation-failedOAuth state provider mismatch.State token was issued for a different providerRestart the OAuth flow with the correct provider
409already-existsThis OAuth account is already linked to another user.OAuth identity already associated with a different accountSign in with the linked account instead
409email-already-existsEmail is already registered to another account.Email from OAuth provider conflicts with existing accountLink accounts or sign in with existing account

Anonymous Auth Errors

StatusSlugMessageWhenHandling
404feature-not-enabledAnonymous authentication is not enabled.anonymousAuth is disabled in server configEnable anonymous auth in config or use a different auth method

Session & Token Errors

StatusSlugMessageWhenHandling
400invalid-inputRefresh token is required.Missing refresh token in request bodyRe-authenticate the user
401invalid-refresh-tokenInvalid refresh token.JWT decoding failed — malformed or tampered tokenClear stored tokens and re-authenticate
401refresh-token-expiredRefresh token expired.Token TTL exceededClear stored tokens and re-authenticate
401refresh-token-reusedRefresh token reuse detected. Session revoked.A previously used refresh token was replayed — possible token theft. The affected session is revokedClear stored tokens and force full re-authentication
401unauthenticatedAuthentication required.Missing or invalid Authorization headerRedirect to sign-in page
Refresh Token Reuse Detection

When EdgeBase detects a refresh token being used more than once, it assumes the token was stolen. The affected session is immediately revoked as a security measure. The user will need to sign in again on that device.


Email Verification Errors

StatusSlugMessageWhenHandling
400invalid-inputVerification token is required.Missing token in requestCheck the verification URL format
400invalid-tokenInvalid or expired verification token.Token not found in the databaseRequest a new verification email
400token-expiredVerification token has expired. Please request a new one.Token TTL exceeded (24 hours)Prompt user to request a new verification email

Password Reset Errors

StatusSlugMessageWhenHandling
400invalid-inputEmail is required.Missing email in reset requestShow form validation
400invalid-inputPassword reset token is required.Missing token in reset confirmationCheck the reset URL format
400invalid-inputNew password is required.Missing new password in reset confirmationShow form validation
400password-too-shortPassword must be at least 8 characters.New password too shortShow password requirements
400invalid-tokenInvalid or expired password reset token.Token not found in the databaseRequest a new password reset email
400token-expiredPassword reset token has expired. Please request a new one.Token TTL exceeded (1 hour)Prompt user to request a new reset email
403hook-rejectedPassword reset was blocked by the beforePasswordReset hook.beforePasswordReset hook returned a rejectionDisplay hook's custom message if provided

Change Password Errors

StatusSlugMessageWhenHandling
400invalid-inputcurrentPassword and newPassword are required.Missing current or new passwordShow form validation
400password-too-shortPassword must be at least 8 characters.New password too shortShow password requirements
401invalid-passwordCurrent password is incorrect.Wrong current password enteredPrompt user to re-enter current password
403oauth-onlyThis account uses OAuth sign-in. Password login is not available.Account was created via OAuth — no password setPassword change is not applicable for OAuth accounts
403anonymous-not-allowedAnonymous accounts cannot change password.Anonymous user attempted password changeLink account with email first via account linking

Account Linking Errors

StatusSlugMessageWhenHandling
400invalid-inputEmail and password are required.Missing fields when linking with email/passwordShow form validation
400password-too-shortPassword must be at least 8 characters.Weak password during email linkShow password requirements
400action-not-allowedAccount linking is not allowed for this account type.Account linking rejected based on account state or configurationCheck the account type and linking requirements
409email-already-existsEmail is already registered.Email already in use by another accountSuggest signing in with that email instead
409already-existsThis OAuth account is already linked.OAuth identity already associated with another accountSign in with the linked account instead

Profile Update Errors

StatusSlugMessageWhenHandling
400invalid-inputemailVisibility must be 'public' or 'private'.Invalid value for emailVisibility fieldUse only 'public' or 'private'
400no-fields-to-updateNo valid fields to update...Request body contains no recognized fieldsCheck available profile fields in the docs

Admin API Errors

StatusSlugMessageWhenHandling
403forbiddenService Key required for admin auth operations.Admin endpoint called without a Service KeyInclude the Service Key in the request header
401unauthenticatedUnauthorized. Service Key required.Invalid or expired Service Key providedVerify your Service Key in server config
404user-not-foundUser not found.User ID does not exist in the databaseVerify the user ID before retrying

Captcha Errors

StatusSlugMessageWhenHandling
403forbiddenCaptcha verification required.Captcha is enabled but no token was provided. Response includes data.captcha_required: trueRender captcha widget and retry with the token
403forbiddenCaptcha verification failed.Captcha token is invalid or expiredReset captcha widget and prompt user to retry
503internal-errorCaptcha service unavailable.Cloudflare Turnstile API is unreachable and failMode is closedShow a temporary error and retry after a delay
Captcha data field

When captcha verification is required, the error response includes extra context:

{
"code": 403,
"message": "Captcha verification required.",
"data": { "captcha_required": true }
}

Use the data.captcha_required flag to programmatically detect when to render the captcha widget.


Rate Limiting

StatusSlugMessageWhenHandling
429rate-limitedToo many requests. Try again later.Global rate limit exceededBack off and retry after a delay
429rate-limitedToo many signup attempts...Signup-specific rate limit exceededShow retry timer
429rate-limitedToo many login attempts...Sign-in-specific rate limit exceeded (per email)Show retry timer
Rate Limit Strategy

Sign-in rate limits are tracked per email address to prevent brute-force attacks against specific accounts while not affecting other users.


SDK Error Handling

All EdgeBase client SDKs throw structured errors that include the code, message, and slug fields from the server response. The slug field is the recommended way to handle errors programmatically -- it is stable across versions and locales, unlike message which may change.

try {
const { user } = await client.auth.signIn({
email: 'user@example.com',
password: 'wrongPassword',
});
} catch (error) {
// Recommended: match on slug for stable, locale-independent handling
switch (error.slug) {
case 'invalid-credentials':
showError('Email or password is incorrect.');
break;
case 'rate-limited':
showError('Too many attempts. Please try again later.');
break;
case 'oauth-only':
redirectToOAuth();
break;
case 'account-disabled':
showError('Your account has been disabled.');
break;
case 'hook-rejected':
showError(error.message); // Display hook's custom message
break;
default:
// Fall back to data field for captcha handling
if (error.data?.captcha_required) {
showCaptcha();
} else {
showError(error.message);
}
}
}

Quick Reference by Status Code

StatusMeaningCommon SlugsCommon Causes
400Bad Requestinvalid-input, validation-failed, invalid-email, password-too-short, invalid-token, token-expiredMissing required fields, invalid format, expired tokens
401Unauthorizedinvalid-credentials, unauthenticated, invalid-refresh-token, refresh-token-expired, refresh-token-reusedInvalid credentials, expired/invalid tokens, missing auth header
403Forbiddenhook-rejected, oauth-only, anonymous-not-allowed, account-disabled, forbiddenHook rejections, OAuth-only accounts, captcha required, anonymous restrictions
404Not Founduser-not-found, feature-not-enabledUser not found, feature not enabled
409Conflictemail-already-exists, already-existsDuplicate email, OAuth account already linked
429Too Many Requestsrate-limitedRate limits (global, signup, or signin)
500Internal Server Errorinternal-errorMissing OAuth provider configuration
503Service Unavailableinternal-errorExternal service unreachable (e.g., Turnstile API)

All Error Slugs

A complete list of well-known error slugs used across the authentication API:

SlugStatusDescription
invalid-input400Input validation failure in auth routes (missing fields, bad format)
validation-failed400Input validation failure in OAuth and admin routes
invalid-email400Email format validation failed
password-too-short400Password shorter than minimum length (8 characters)
password-too-long400Password exceeds maximum length (256 characters)
invalid-token400Token is malformed or not found
token-expired400Token has exceeded its TTL
no-fields-to-update400No recognized fields in the update request body
invalid-otp400OTP code is invalid or expired
unauthenticated401Missing or invalid authorization header
invalid-credentials401Wrong email or password during sign-in
invalid-password401Wrong current password during password change
invalid-refresh-token401Refresh token is malformed or tampered
refresh-token-expired401Refresh token TTL exceeded
refresh-token-reused401Refresh token replayed (possible theft -- all sessions revoked)
forbidden403General access denied
oauth-only403Account uses OAuth -- password operations not available
anonymous-not-allowed403Anonymous accounts cannot perform this action
account-disabled403Account has been disabled by an administrator
hook-rejected403Auth hook rejected the operation
action-not-allowed403Requested auth action is not allowed by config
user-not-found404User ID does not exist
feature-not-enabled404Requested feature is not enabled in server config
email-already-exists409Email already registered to another account
already-exists409Resource already exists (OAuth link, etc.)
rate-limited429Too many requests -- back off and retry
internal-error500Internal server error