Skip to main content

Troubleshooting & Rate Limits

Common errors, what they mean, and the rate limits that protect the service.

Error responses

  • OAuth endpoints (/oauth2/*) return standard OAuth2 errors (RFC 6749): a JSON body with an error code (and often error_description).
  • Admin/API endpoints (/api/*) return a JSON body { "error": "<code>", "message": "…" } with an appropriate HTTP status.

OAuth errors

errorTypical causeFix
invalid_requestMissing/invalid parameter, or a redirect_uri that isn't registered.Check the request; register the exact redirect URI.
invalid_grantExpired/invalid authorization code, or a reused/expired refresh token.Restart the flow; use the newest refresh token (they rotate — see Token Lifecycle).
invalid_clientWrong client ID or missing/invalid API key on a confidential client.Verify the client ID and API key.
invalid_tokenThe presented token is expired, malformed, or revoked.Refresh the access token or re-authenticate.
unsupported_grant_typeA grant_type Curupira doesn't support.Use authorization_code or refresh_token.

API errors

HTTPerrorMeaning
400bad_request / validation_errorMalformed or invalid input (e.g. a redirect URI without http(s)://).
401unauthorizedNo or invalid session/credential.
403forbiddenAuthenticated, but lacking the required permission (or out of tenant scope).
404not_foundThe resource doesn't exist (or isn't visible to your tenant).
409conflict / last_adminState conflict — e.g. removing the last admin of a tenant.
429too_many_requestsRate-limited (see below) — honor the Retry-After header.
500internal_server_errorUnexpected server error; retry, and contact support if it persists.

Rate limits & lockout

Curupira protects authentication endpoints two ways:

Login brute-force protection

Repeated failed logins trigger a temporary lockout with exponential backoff — after a small threshold of failures (≈5) the base lock is ~60 seconds and roughly doubles with each further failure, capped at ~15 minutes. Blocked attempts return 429 with a Retry-After header. Wait for the Retry-After interval, then retry — a correct login after the window succeeds. (The thresholds are deployment-tunable.)

IP rate limiting

Endpoints are rate-limited per client IP (tunable via the deployment's RATE_LIMIT_* settings; the built-in defaults are deliberately tight — e.g. ~60 requests/minute on login). Exceeding a limit returns 429 too_many_requests. Clients should respect Retry-After and back off rather than hammering the endpoint.

:::tip Design for 429s Treat 429 as a normal, recoverable condition: read Retry-After, wait, and retry with exponential backoff. Don't retry immediately in a tight loop — that only prolongs the limit. :::

Common issues

  • "redirect_uri mismatch" / invalid_request at login — the redirect_uri must match a registered URI exactly (scheme, host, path, no trailing-slash differences). See Tenant Onboarding.
  • Refresh suddenly fails with invalid_grant — you reused an old refresh token. Store and use the new one returned by each refresh (Token Lifecycle).
  • 403 on an admin action — your admin account lacks that permission, or the resource is in another tenant. Check your role assignment.
  • SSO login refused for a missing/unverified email — the provider didn't return a verified email; Curupira requires one to provision or link an account. See SSO Provider Setup.

Getting help

  • The OpenID discovery document lists the live endpoints and capabilities.
  • Admins can inspect the Logs views (login attempts, events, audit) in the dashboard to see what happened server-side.