Febasi Docs
Reference

Errors

The error envelope, every error code the Auth API returns, and what each one means in practice.

Every Auth API response follows the same envelope:

{ "success": true,  "data":  { "..." : "..." } }
{ "success": false, "error": "Human-readable message", "code": "MACHINE_CODE" }

Validation failures (Zod) include a details array describing each invalid field:

{
  "success": false,
  "error": "Validation failed",
  "code": "VALIDATION_ERROR",
  "details": [
    { "path": ["password"], "message": "String must contain at least 6 character(s)" }
  ]
}

The HTTP status code is meaningful — match on code for fine-grained behavior, on the status code for coarse routing.

Auth & sessions (401)

CodeWhen
UNAUTHORIZEDNo Authorization header / no Client Key on a protected route.
INVALID_CREDENTIALSWrong password, missing user, or INACTIVE user (deliberately ambiguous).
INVALID_TOKENToken signature invalid, malformed, or revoked.
TOKEN_EXPIREDAccess token's exp is in the past.

Authorization (403)

CodeWhen
FORBIDDENAuthenticated, but missing the required permission/scope.
HIERARCHY_VIOLATIONTrying to manage a role/user at or above the actor's level.
PROTECTED_RESOURCETrying to modify a system role (e.g. super_admin).
CROSS_TENANT_ACCESSThe resource belongs to a different tenant than the caller.

HIERARCHY_VIOLATION includes both actorLevel and targetLevel in details — useful for UI messages.

Resource not found (404)

CodeWhen
TENANT_NOT_FOUNDThe tenantCode (or tenant id) does not resolve.
USER_NOT_FOUNDThe user id does not exist in the caller's tenant.
ROLE_NOT_FOUNDThe role id does not exist.
PERMISSION_NOT_FOUNDThe permission id does not exist.

Validation & conflict (400 / 409)

CodeWhen
VALIDATION_ERRORBody / query / params failed Zod schema validation.
PASSWORD_POLICY_VIOLATIONPassword fails the tenant's policy on register or update. Includes violations[].
CONFLICTDuplicate identifier (email, username, CPF/CNPJ already taken in this tenant).

Rate / capacity (429)

CodeWhen
RATE_LIMIT_EXCEEDEDThe route's per-IP rate limit is exhausted.
SESSION_LIMIT_EXCEEDEDThe user is at the tenant's max-concurrent-sessions cap (when configured to reject rather than rotate). Includes currentSessions and maxSessions.

Server-side (500)

CodeWhen
INTERNAL_ERRORCatch-all for unexpected exceptions. The response body never leaks stack traces in production.

If you see INTERNAL_ERROR, capture the timestamp and tenant code; the service writes a structured Pino log line for every one of them and they're correlated by request id.

Treat code, not message

Messages are intentionally human-friendly and may change. The code field is the stable contract.

401 → refresh, not relogin

On TOKEN_EXPIRED, refresh first; on INVALID_TOKEN or INVALID_CREDENTIALS, force a relogin.

403 → check the code

FORBIDDEN means "you don't have the permission". HIERARCHY_VIOLATION means "the action would violate the level rule" — the user might still fix it by escalating, instead of giving up.

409 is recoverable

CONFLICT is the user-friendly path: surface "already taken" to the user instead of a generic error.

On this page