Errors
rakomi_flutter never throws across its public API for expected failure conditions —
sign-in, refresh, and MFA failures all surface as AuthState.error(SdkError(...)), either as
the return value of the call or as an item on authStateChanges. The one exception is
programmer error (an invalid constructor argument, or calling an unsupported method the wrong
way) — those throw synchronously, because they indicate a bug in the calling code, not a runtime
condition to branch on.
Reading an SdkError
Section titled “Reading an SdkError”if (state is AuthStateError) { final SdkError error = state.error; switch (error.code) { case SdkErrorCode.invalidCredentials: case SdkErrorCode.signInFailed: // show "invalid email or password" break; case SdkErrorCode.networkError: // show "network error, try again" break; case SdkErrorCode.mfaStepUpRequired: // switch to the TOTP step; error.errorMessage carries the challengeId break; default: // generic fallback }}SdkError carries code (SdkErrorCode), reason (SdkErrorReason, a finer-grained
discriminator), an optional errorMessage, an optional providerError (from an OAuth
provider’s callback), and an optional cause. Any bearer token or JWT-shaped substring inside
errorMessage/providerError is redacted before toString()/toJson() renders it, so it is
safe to log an SdkError’s string form.
SdkErrorCode
Section titled “SdkErrorCode”| Code | Meaning |
|---|---|
refreshFailed | The refresh-token exchange failed (see reason for why). |
oauthCallbackError | The OAuth callback carried an error, or failed validation. |
tenantSuspended | The tenant is suspended. |
csrfMismatch | The OAuth state parameter did not match the persisted value. |
codeExchangeFailed | The authorization-code-for-token exchange failed. |
signInFailed | A password sign-in/sign-up attempt failed. |
invalidConfig | The SDK was misconfigured. |
networkError | A network-level failure (no response, or an unexpected non-2xx). |
providerError | The identity provider itself returned an error. |
biometricError | A biometric unlock attempt failed — see reason. |
storageError | Persisting to secure storage failed. |
rateLimited | The request was rate-limited. |
invalidCredentials | The submitted credentials were rejected. |
mfaStepUpRequired | Primary sign-in succeeded but a second factor is required; errorMessage carries the challengeId. |
mfaStepUpUnavailable | MFA step-up was requested but the user has no factor configured for it. |
unknown | An unclassified failure. |
SdkErrorReason
Section titled “SdkErrorReason”A finer-grained discriminator, most useful for OAuth-flow and biometric-gate failures.
OAuth flow:
| Reason | Meaning |
|---|---|
oauthUserCancelled | The user dismissed the system browser without completing sign-in. |
oauthLocked | A concurrent OAuth attempt is already in progress. |
oauthStateMismatch | The state (CSRF) or iss (RFC 9700 §4.4 mix-up defense) check failed. |
oauthRedirectMismatch | The callback redirect did not match what was configured. |
oauthMissingParams | The callback was missing code, state, or the one-time id. |
oauthProviderError | The provider itself returned an error, or the system browser could not be launched. |
Biometric gate:
| Reason | Meaning |
|---|---|
biometricCancelled | The user cancelled the biometric prompt. |
biometricLockout | Too many failed attempts — may be transient or permanent (device-dependent). |
biometricNotEnrolled | No biometric is enrolled on the device. |
biometricUnavailable | Biometric hardware is unavailable or disabled (for example, no device passcode set). |
Session lifecycle:
| Reason | Meaning |
|---|---|
sessionExpired | The session has expired. |
sessionRevoked | The session was revoked. |
refreshExpired | The refresh token itself has expired (HTTP 401 on refresh). |
refreshRevoked | The refresh token was revoked (HTTP 403 on refresh, or reuse detected). |
refreshNetwork | A network failure occurred specifically during a refresh attempt. |
certPinMismatch | The server’s TLS certificate did not match a configured pin. |
Generic:
| Reason | Meaning |
|---|---|
network | A generic network-level failure. |
unknown | Unclassified. |
Programmer errors (throw synchronously)
Section titled “Programmer errors (throw synchronously)”A small number of calls throw instead of returning an SdkError, because they represent a
mistake in how the SDK is being used rather than a runtime condition an end user triggered:
RakomiProvider(apiBaseUrl: ..., jwksUrl: ...)— an invalid URL (nothttps://and not the documented dev-loopback exception) throwsArgumentErrorat construction time. See Configuration.performSocialSignIn(...)— an invalid or bannedredirectUrischeme throwsArgumentErrorbefore any network call. See Authentication.RakomiAuth.signInWithProvider(...)andRakomiAuth.verifyMfa(...)(the bare controller methods, as opposed toperformSocialSignIn/verifyMfaImpl) throwUnsupportedErrorby design — they exist to point you at the correct entry point. See Authentication.
Advanced: DPoP refresh failures
Section titled “Advanced: DPoP refresh failures”If you have opted a session into DPoP sender-constrained refresh,
a bound refresh can additionally fail with a dpop_prover_unavailable or invalid_dpop_proof
condition, surfaced through the same SdkError envelope (code: refreshFailed or
networkError, with the DPoP-specific wire code carried on errorMessage for diagnostics). A
DPoP proof failure never silently falls back to an unbound (Bearer) request.