Skip to content

Error codes

Every error response has the same shape:

json
{ "code": "not_found", "message": "record not found: posts/01HXY..." }

The HTTP status code is sufficient for clients that don't care about the specifics; code lets you branch on the cause.

Status → code mapping

HTTPcodeWhen
400validationRequest body failed validation (missing required field, wrong type, etc.).
400policy_violationA write tried to set a value outside the cascade-bound.
400unknown_columnFilter referenced a column the collection doesn't have.
400parse_errorFilter expression couldn't be parsed.
401unauthorizedMissing or invalid Authorization header.
401bad_credentialsLogin failed: wrong password / unknown email / wrong OTP.
401mfa_requiredReturned with 202 during the two-step TOTP login. The body has {challenge_id}; follow up with /auth/users/login/totp.
403forbiddenAuthenticated but not allowed (scope / role / access rule).
404not_foundThe target object doesn't exist. message says what was missing.
404realm_not_foundSpecifically the realm in the URL doesn't exist.
404app_not_foundSpecifically the app in the URL doesn't exist.
409conflictDuplicate id, duplicate email, master admin already set, etc.
413payload_too_largeFile upload exceeds the storage cap.
422(json)Request couldn't be deserialized at all. Axum/Serde rejection.
500internalUnhandled error path. Check server logs.
503uninitializedServer hasn't completed first-run setup. Only /healthz and /_/setup are reachable.

Validation errors

validation errors are produced by the validator crate. The message field includes all field errors joined together, e.g.:

"email: invalid email; password: length(min=8): is too short"

If you need structured field-level errors, the dashboard parses this format; clients are encouraged to surface the whole message verbatim or split on ; for per-field lines.

Policy-violation errors

json
{
  "code":    "policy_violation",
  "message": "field=password.length value={min:4,max:64} outside bound master={min:8,max:128}"
}

These come from the cascade engine. The message always names the field, the offending value, and the parent scope's bound that was violated.

What server logs say

For every non-2xx response, the server emits a structured tracing::warn! with the request id, the realm, the app, and the inner error. Look there for the stack trace and the underlying sqlx/object_store error when code: internal shows up.

RUST_LOG=info,rustbase_api=debug ./rustbase

…will get you the per-handler error reason without flooding you with sqlx chatter.

Idempotency

None of the destructive endpoints (DELETE /api/...) support an Idempotency-Key header today. Retries are safe (deleting a missing thing → 404, no destructive side-effect). For creates, generate the id client-side if you need idempotent retries — RustBaas will respect the supplied id field on most create endpoints.

Released under the MIT OR Apache-2.0 license.