Ir al contenido

Códigos de error

Cada fallo que devuelve un backend de Rebase utiliza un único envelope y contiene un code estable. El código es el elemento sobre el que bifurcar la lógica: el mensaje está escrito para personas y puede reformularse, el estado se comparte entre una docena de problemas diferentes y el código no sufre ninguno de esos dos casos.

{
"error": {
"message": "Schema drift: table \"posts\" does not exist.",
"code": "SCHEMA_DRIFT",
"details": { "dbCode": "42P01" },
"requestId": "6f1b2f3e-8a0c-4d1b-9c3e-2a5b7c9d1e0f"
}
}
  • message — legible para humanos. Para un 4xx es el propio mensaje del servidor; para un 5xx es deliberadamente genérico, ya que el texto subyacente puede citar un host, un rol o un nombre de columna.
  • code — uno de los valores a continuación. Estable entre versiones menores.
  • details — opcional y nunca garantizado. Consulta las reglas a continuación.
  • requestId — presente siempre que la solicitud haya pasado por el middleware de request-ID, que incluye cada ruta bajo basePath.

Cada solicitud bajo basePath obtiene un ID: la cabecera X-Request-ID del cliente cuando es un UUID v4 válido; de lo contrario, uno nuevo. Se devuelve en la respuesta como X-Request-ID, se incluye en el envelope de error como requestId y se adjunta a la línea de log del servidor para esa solicitud.

Esa es la clave de unión. Inclúyela en un reporte de error y un operador podrá encontrar la línea de log exacta que explica el fallo, con la razón que nunca se mostró al cliente.

Enviar el tuyo propio es la forma en que una traza sobrevive a un salto: una pasarela (gateway) o un ejecutor de tareas (job runner) que reenvía la cabecera obtiene un único ID a través de cada servicio que gestionó la solicitud. Un valor inválido se ignora en lugar de ser rechazado —no vale la pena hacer fallar una solicitud por una cabecera malformada del cliente—, así que no asumas que el ID que enviaste es el ID que obtuviste. Lee la cabecera de respuesta.

details es de diagnóstico, no contractual. Tres reglas lo rigen:

  1. Todo lo que una ruta establece explícitamente se devuelve siempre. Estos son los propios errores del cliente descritos con precisión: qué campo de filtro era desconocido, qué relación no es escribible, qué valor no coincidía con su tipo.
  2. Los diagnósticos de la base de datos se recortan en producción. Cuando el fallo proviene de Postgres, details.dbCode —el SQLSTATE— está siempre presente: nombra la clase del problema y no revela nada sobre los datos. dbMessage, detail y hint solo se añaden cuando NODE_ENV no es production, ya que Postgres incluye el contenido de las filas en ellos. 23505 reporta Key (email)=(a@b.c) already exists., lo que respondería a “¿está registrada esta persona?” para cualquier dirección que alguien decida probar.
  3. Nunca bifurques la lógica basándote en details. Hazlo según code. Lo que está bajo details es lo que resultaba útil para una persona en ese punto de llamada, y puede cambiar.
Estado Lo que indica sobre la solicitud
400 Malformada, o solicitando algo que no existe en el esquema. Corrige la solicitud.
401 No autenticado, o la credencial ha expirado. Inicia sesión o refresca el token.
403 Autenticado, pero no autorizado. Reintentar con la misma identidad no servirá.
404 No existe tal ruta, colección o fila —o es una fila que la seguridad a nivel de fila oculta.
409 Un conflicto con el estado existente: un duplicado o una escritura concurrente.
413 415 422 El cuerpo es demasiado grande, el tipo de medio es incorrecto o fue rechazado semánticamente.
429 Límite de tasa alcanzado. Reduce la frecuencia de peticiones; el mensaje indica durante cuánto tiempo.
500 El problema está en el servidor o su base de datos, no en el cliente. Revisa los logs.
501 La ruta existe, pero este despliegue no puede atenderla: una funcionalidad desactivada o sin configurar.
502 503 504 Una dependencia fue inaccesible, no está configurada o fue demasiado lenta.
Código Estado Significado Qué hacer
AAL2_REQUIRED 403 La ruta necesita un segundo factor y la sesión solo tiene uno. Completa el desafío MFA y vuelve a intentarlo.
ALREADY_VERIFIED 400 La dirección o el factor ya están verificados. Nada: el estado deseado ya se cumple.
ACCOUNT_OUTRANKS_CALLER 403 La cuenta que se edita, restablece o elimina tiene un rol o un alcance que el llamante no tiene. details.beyond los nombra. Haz que el cambio lo haga alguien que los tenga.
ANONYMOUS_AUTH_DISABLED 403 El inicio de sesión anónimo está desactivado en este servidor. Habilítalo o inicia sesión con una identidad real.
API_KEY_SELF_MANAGEMENT_FORBIDDEN 403 Una clave de API intentó listar, crear, cambiar o revocar claves de API, ya sean de su mismo tipo o personales. Gestiona las claves como una persona que tenga keys:write, o con la clave de servicio.
AUTH_MIDDLEWARE_MISSING 500 Se ejecutó una ruta protegida sin ningún middleware de autenticación de Rebase previo, por lo que nunca se evaluó la credencial del cliente. Monta la app a través del router de funciones en lugar de directamente sobre tu propio servidor.
BOOTSTRAP_ANONYMOUS 403 Un cliente anónimo intentó el bootstrap del primer administrador. Inicia sesión primero.
BOOTSTRAP_COMPLETED 403 El primer administrador ya existe. Haz que un administrador existente otorgue el rol.
BOOTSTRAP_NOT_FIRST_USER 403 El bootstrap es solo para el primer usuario absoluto, y este no lo es. Haz que un administrador existente otorgue el rol.
CAPTCHA_FAILED 400 El proveedor rechazó el token CAPTCHA. Resuelve un nuevo desafío.
CAPTCHA_REQUIRED 400 La ruta requiere un token CAPTCHA y no se envió ninguno. Incluye el token.
CHALLENGE_EXHAUSTED 401 Demasiados códigos incorrectos para un mismo desafío MFA. Inicia un nuevo desafío.
EMAIL_EXISTS 409 Ya existe una cuenta con esa dirección — en el registro, en un cambio de dirección, y al seguir un enlace de cambio de dirección cuando otra cuenta tomó la dirección mientras esperaba. Inicia sesión, o inicia un restablecimiento de contraseña; para un cambio de dirección, elige otra dirección.
EMAIL_NOT_CONFIGURED 503 Se solicitaron enlaces mágicos u OTP y el servidor no tiene transporte de correo. Configura SMTP o usa otro método de inicio de sesión.
EMAIL_NOT_VERIFIED 403 La cuenta existe y su dirección no está verificada. Verifica la dirección.
FACTOR_NOT_VERIFIED 400 El factor MFA fue registrado pero nunca confirmado. Confirma el factor.
IDENTITY_ALREADY_LINKED 409 Esa identidad OAuth pertenece a otra cuenta. Inicia sesión con ella o desvincúlala allí primero.
IMPERSONATION_FORBIDDEN 403 Una petición envió x-rebase-impersonate y quien llama no puede ejecutar una petición como otro usuario. Solo puede la sesión propia de un administrador que ha iniciado sesión, nunca una clave de API ni la clave de servicio. Envíala con la sesión de un administrador, o quita la cabecera.
IMPERSONATION_INVALID 400 x-rebase-impersonate se envió vacía. Envía el uid del usuario como el que actuar, o quita la cabecera.
IMPERSONATION_TARGET_NOT_FOUND 404 x-rebase-impersonate no nombra a ningún usuario activo: ninguna cuenta tiene ese uid, o está desactivada. Comprueba el uid.
IMPERSONATION_UNAVAILABLE 501 La autenticación de este backend no puede ejecutar una petición como otro usuario, porque su AuthAdapter no tiene resolveUser. Implementa resolveUser en el adaptador, o quita la cabecera.
IMPERSONATION_UNSUPPORTED 400 Se envió x-rebase-impersonate a una ruta que no puede ejecutarse como otro usuario. Solo la API de datos y las funciones personalizadas lo respetan, y el socket en tiempo real respeta impersonate en AUTHENTICATE. Envía la petición sin la cabecera.
INVALID_ACCOUNT 400 La cuenta se encuentra en un estado sobre el que esta operación no puede actuar. Consulta el mensaje.
INVALID_CHALLENGE 400 El desafío MFA es desconocido o ha expirado. Inicia uno nuevo.
INVALID_CODE 400 / 401 El código OTP o MFA es incorrecto: 400 en el inicio de sesión por código de correo (/auth/otp/verify), 401 en un registro o desafío de MFA. Reintenta con el código actual.
INVALID_CREDENTIALS 401 Correo electrónico o contraseña incorrectos (deliberadamente no se especifica cuál). Reintenta o restablece la contraseña.
INVALID_PLATFORM_TOKEN 401 Se rechazó un token de plataforma rpt_: firma incorrecta, audiencia equivocada, caducado o una vida útil por encima del límite. El mensaje dice cuál. Haz que la plataforma emita uno nuevo; en Rebase Cloud, vuelve a ejecutar el comando.
INVALID_SCOPES 400 Se pidió para una clave algo que no es un alcance: mal formado, desconocido o con un destino que el alcance no admite. details.problems dice cuál y por qué; details.validScopes enumera los alcances que una clave puede tener. Desde 0.25 Deja fuera keys:read y keys:write, que ninguna clave puede tener; en la 0.24 los enumera. Usa un nombre de la lista. Consulta Roles y alcances.
INVALID_TOKEN 400 / 401 Un token de verificación, restablecimiento, enlace mágico o cambio de dirección está malformado, es desconocido, ya se consumió o ha expirado (400). Una credencial de proveedor OAuth o un refresh token que no se puede verificar es un 401. Solicita un enlace nuevo, o vuelve a iniciar sesión.
KEY_MANAGEMENT_SCOPE 400 Se pidió keys:read o keys:write para una clave. Ninguna clave puede gestionar claves. details.scopes los nombra. Déjalos fuera.
LAST_ADMIN 403 El cambio dejaría al proyecto sin administradores. Promociona a otra persona primero.
MFA_REQUIRED 401 La contraseña era correcta y la cuenta tiene un segundo factor verificado, por lo que el inicio de sesión está a medio completar. details contiene un token de corta duración con ámbito para el desafío MFA; no es una sesión. Inicia un desafío y respóndelo; la respuesta al desafío emite la sesión.
NO_SESSION 401 No se presentó ninguna cookie de sesión ni refresh token. Normal en la primera carga de una página. Inicia sesión.
NOT_ANONYMOUS 400 Se llamó a una ruta de actualización desde anónimo con una cuenta real. Nada que actualizar.
OAUTH_ERROR 401 El proveedor de OAuth lo rechazó o devolvió un error. Reintenta el flujo; el mensaje contiene el motivo del proveedor.
PERSONAL_KEYS_DISABLED 403 Las claves de API personales están desactivadas en este backend. Establece personalKeys: true en el bloque auth de la colección de usuarios.
PERSONAL_KEY_NEEDS_ACCOUNT 403 La clave de servicio o una sesión de invitado intentó usar las rutas de claves personales. Ninguna de las dos tiene una cuenta como la que pueda actuar una clave. Inicia sesión en una cuenta, o crea una clave de servicio en /api/admin/api-keys.
PLATFORM_TOKENS_OFF 401 Un token de plataforma rpt_ llegó a un servidor que no los acepta: REBASE_PLATFORM_TOKEN_KEY y REBASE_PLATFORM_TOKEN_AUDIENCE no están definidas. La plataforma que aloja la app define ambas al desplegar; vuelve a desplegar o inicia sesión en la app de otra forma.
RATE_LIMITED 429 Demasiados intentos desde este cliente. Reduce la frecuencia de peticiones; el mensaje indica durante cuánto tiempo.
REDIRECT_URI_NOT_ALLOWED 400 El destino de redirección no está en la lista de permitidos. Añádelo a la configuración del proveedor.
REGISTRATION_DISABLED 403 El registro de autoservicio está desactivado. Haz que un administrador cree la cuenta.
ROLE_EXCEEDS_CALLER 403 Los roles que se conceden tienen un alcance, o admin, que el llamante no tiene. details.beyond los nombra. Haz que conceda el rol alguien que los tenga.
ROLE_EXCEEDS_CREATOR 403 Se dio a una clave de servicio un rol de RLS que su creador no tiene. Solo un administrador puede dar cualquier rol. details.roles los nombra. Quita el rol, o haz que un administrador cree la clave.
ROLE_EXISTS 409 Ese nombre de rol ya está en uso. Elige otro nombre.
ROLE_LOOKUP_FAILED 503 No se pudieron leer los roles del llamante — en una ruta de administración, o en una solicitud de datos en un backend con config.auth. Falla de forma cerrada en lugar de confiar en los roles del token. Un token cuyo uid no nombra ninguna cuenta, incluido un uid que la tabla de usuarios no puede contener, es un 401, no esto (Desde 0.25; en la 0.24 un uid que la tabla no puede contener es este 503). Una base de datos a la que no se puede llegar es DATABASE_UNAVAILABLE, no esto (Desde 0.25; en la 0.24 es este 503). Reintenta; revisa la base de datos.
SCOPE_EXCEEDS_CREATOR 403 Se pidió para una clave un alcance que su creador no tiene. Una clave nunca tiene más que la cuenta que la crea. details.scopes los nombra. Quítalos, o haz que cree la clave alguien que los tenga.
SCOPE_MISSING 403 La credencial no tiene el alcance que necesita esta ruta, colección, origen de almacenamiento o función. details.requiredScope lo nombra, destino incluido. Para una persona, un rol que declare el alcance. Para una clave, una clave que lo tenga. Consulta Roles y alcances.
SCOPE_NOT_DECLARED 500 Desde 0.25 Una ruta protegida con requireScope nombra un alcance de la aplicación que este backend no declara, así que nadie lo tiene, tampoco un administrador. Un nombre que no es un alcance en absoluto, o uno integrado mal escrito como data:raed, nunca llega hasta aquí: requireScope lanza un error donde se registra la ruta. En la 0.24 ambos responden a todos los llamantes 403 SCOPE_MISSING. Declara el alcance bajo auth.scopes en la colección de usuarios, o corrige el nombre. Consulta Roles y alcances.
SELF_DELETE 400 Un administrador intentó eliminar su propia cuenta. Haz que lo haga otro administrador.
SESSION_REVOKED 401 Se cerró la sesión en otro lugar, se revocaron todas las sesiones, o se eliminó la cuenta. Todas las puertas que aceptan una sesión lo responden a un token de acceso así: la API de datos, el almacenamiento, las funciones personalizadas y las rutas de administración (Desde 0.25; en la 0.24 las tres primeras responden UNAUTHORIZED “Invalid or expired token”). El SDK renueva la sesión, la renovación se rechaza y cierra la sesión. Inicia sesión de nuevo.
ACCOUNT_DISABLED 401/403 Un administrador deshabilitó la cuenta: el inicio de sesión (403), y la renovación y todos los tokens que tiene (401), se rechazan, en todas las puertas que aceptan una sesión (Desde 0.25; en la 0.24 la API de datos, el almacenamiento y las funciones personalizadas responden UNAUTHORIZED). Pide ayuda a un administrador.
EMAIL_NOT_CONFIRMED 403 requireEmailVerification está activado y la dirección aún no está verificada. Solo se responde así cuando la contraseña es correcta; se envía un enlace nuevo por correo. Sigue el enlace del correo.
PROOF_REQUIRED 409 POST /auth/verify-email: la cuenta tiene una contraseña o una identidad que nadie demostró, y la solicitud no demuestra ninguna de las dos. El token no se consume. Envía password para conservarla, o removeUnproven: true para verificar sin ella.
UNDELIVERABLE_ADDRESS 400 / 409 Se pidió un correo de verificación para una dirección que el correo no puede alcanzar — la de un invitado, o el marcador de posición de X (400) — o una cuenta pidió pasar a una dirección así (409, POST /auth/change-email). Define primero una dirección real.
EMAIL_UNCHANGED 400 POST /auth/change-email indicó la dirección actual de la cuenta. No hay nada que cambiar.
ANONYMOUS_USER 403 Un invitado pidió cambiar su dirección de correo; un invitado no tiene una propia. Conviértelo primero en una cuenta (POST /auth/anonymous/link).
MFA_NOT_ENROLLED 400 Se pidieron códigos de recuperación para una cuenta sin un segundo factor verificado. Registra primero un factor.
HOOK_REJECTED 400 Un hook beforeUserCreate, beforeLogin, beforeUserDelete o beforeEmailChange lanzó un error. El mensaje es el del hook; un hook que eligió un estado 4xx responde con él. Consulta el mensaje.
INVALID_JSON 400 El cuerpo de la solicitud no es JSON. Envía un cuerpo JSON.
SELF_DISABLE 400 Un administrador intentó deshabilitar su propia cuenta. Pide a otro administrador que lo haga.
NOT_SUPPORTED 501 El repositorio de autenticación de este backend no puede hacer lo que se pidió (deshabilitar cuentas, cambiar una dirección). Reinicia el servidor para que se añada la columna, o usa un repositorio que lo admita.
UNKNOWN_SCOPE_TARGET 400 El destino de un alcance nombra una colección, un origen de almacenamiento o una función que este backend no sirve. details enumera los que sí sirve. Corrige el destino.
UNVERIFIED_IDENTITIES 409 Un enlace mágico, código por correo o restablecimiento de contraseña demostró la dirección de una cuenta no verificada, y la cuenta tiene una identidad de inicio de sesión cuyo proveedor nunca verificó esa dirección. El repositorio de autenticación no puede eliminarla (no tiene unlinkUserIdentity), así que la prueba se rechaza en lugar de dejar esa vía de acceso en una cuenta verificada. Implementa unlinkUserIdentity en el repositorio de autenticación propio, o pide a un administrador que revise la cuenta.
SETUP_REQUIRED 403 El proyecto aún no tiene administrador, por lo que esta ruta no está disponible. Completa la configuración del primer administrador.
TOKEN_ALREADY_USED 401 Se reutilizó un token de un solo uso, o llegó un refresh token que se rotó hace más de refreshTokenReuseIntervalSeconds. Solicita uno nuevo, o vuelve a iniciar sesión.
TOKEN_EXPIRED 401 El token ha superado su tiempo de vida. Solicita uno nuevo.
USER_NOT_FOUND 404 No hay cuenta con ese id. Verifica el id.
WEAK_PASSWORD 400 La contraseña no cumple con la política de contraseñas (por defecto, 8 o más caracteres con una mayúscula, una minúscula y un dígito) — al registrarse, al restablecerla o cambiarla, y en la contraseña elegida por un administrador: POST /api/admin/users, una creación en la colección de usuarios a través de la API de datos, PUT /api/admin/users/:id o POST /api/admin/users/:id/reset-password. Elige una más robusta. Un administrador que importa cuentas puede enviar skipPasswordPolicy: true en una creación.
Código Estado Significado Qué hacer
AGGREGATE_NOT_SUPPORTED 501 Este driver no puede calcular el agregado solicitado. Usa un driver que pueda, o calcúlalo en el cliente.
BRANCHING_UNSUPPORTED — Se solicitó una rama de la base de datos mediante el websocket de Studio en la base de datos de desarrollo administrada (PGlite), donde una rama es la principal y nada quedaría aislado. El rechazo es el mismo que imprime rebase db branch. Apunta DATABASE_URL a tu propio Postgres (rebase dev --docker inicia uno) y crea la rama allí.
BATCH_TOO_LARGE 400 POST /api/data/_batch contiene más operaciones que el límite por lote (1000 por defecto). Un lote es una sola transacción y mantiene sus bloqueos durante toda ella. Envíalo en fragmentos; el mensaje indica el límite y tu recuento.
BATCH_UNSUPPORTED 400 El driver de este backend no puede escribir en múltiples colecciones de forma atómica, y un bucle de escrituras individuales no sería atómico ni de un solo viaje de ida y vuelta. Envía las escrituras como solicitudes separadas, o como llamadas /bulk por colección.
BULK_TOO_LARGE 400 El cuerpo de la operación masiva excede el límite configurado de elementos. Divide la solicitud.
BULK_UNSUPPORTED 400 Esta colección o driver no admite escrituras masivas. Escribe las filas una por una.
CALLBACK_REJECTED 400 Un callback de colección rechazó la escritura. Un throw desde beforeSave/beforeDelete/after* es un 400 que contiene el propio mensaje del autor; un beforeDelete que devuelve false es un 403. details.stage indica qué callback, details.path la colección. Lee el mensaje: fue redactado por este proyecto, no por Rebase.
CALLBACK_RECURSION 500 Las escrituras iniciadas por hooks se anidaron más de 16 niveles: la escritura de context.data de un hook vuelve a ejecutar los hooks de esa colección, y nada en la cadena la detiene — normalmente un afterSave que actualiza su propia fila sin condición. Toda la escritura se revirtió. El mensaje nombra el hook y la colección; details.chain enumera cada paso hook → escritura. Haz condicional la escritura del hook: actúa solo cuando status === "new", o omítela cuando values ya tenga lo que escribiría.
CURSOR_WITH_OFFSET 400 Se combinó ?after= con ?offset= o ?page=. Un cursor ya indica dónde comienza la página, por lo que un desplazamiento sobre él omite silenciosamente esa cantidad de filas después del cursor —una brecha que el cliente no puede ver en la respuesta. Usa uno u otro.
DISTINCT_NOT_APPLICABLE 400 Se combinó ?distinct=true con una consulta de búsqueda o vectorial. Ambas adjuntan una puntuación por fila, por lo que nunca habrá dos filas iguales y DISTINCT no colapsaría nada; parecería haber funcionado sin cambiar nada. Descarta uno de los dos.
DISTINCT_ORDER_BY_NOT_SELECTED 400 Una lectura con distinct está ordenada por una columna que no devuelve. Un SELECT DISTINCT solo puede ordenarse por columnas en su lista de selección, o las filas que colapsa no tendrían un orden definido. details.fields los enumera. Añade esos campos a ?fields=, o elimínalos de ?orderBy=.
DATABASE_UNAVAILABLE 503 Desde 0.25 No se pudo llegar a la base de datos: la conexión fue rechazada o se cortó, el host no se resolvió, o el servidor se está apagando o arrancando. Todas las puertas responden con él, incluidos el inicio de sesión, las rutas de administración y el socket de tiempo real (un frame ERROR). Se envía con Retry-After: 5. En la 0.24 la misma caída responde ROLE_LOOKUP_FAILED, INTERNAL_ERROR o un 500 con el código ECONNREFUSED. Reintenta; el SDK lo hace. Comprueba que la base de datos esté en marcha y accesible desde el servidor.
DB_CONNECT_TIMEOUT 503 Abrir una nueva conexión a la base de datos tardó más que DB_POOL_CONNECT_TIMEOUT: la base de datos es lenta para aceptar conexiones, o está lejos. Se envía con Retry-After. Reintenta; el SDK lo hace. Revisa la carga de la base de datos y la red hacia ella.
DB_PERMISSION_DENIED 500 Postgres rechazó la sentencia (42501): una política de seguridad a nivel de fila que deniega este rol, o un GRANT faltante. Consulta Troubleshooting.
DB_POOL_EXHAUSTED 503 Todas las conexiones del pool de la base de datos estuvieron ocupadas durante DB_POOL_CONNECT_TIMEOUT, por lo que esta solicitud nunca llegó a la base de datos. Es carga, no un fallo; se envía con Retry-After. El servidor registra el remedio una vez por minuto. Reintenta; el SDK lo hace. Aumenta DB_POOL_MAX, o busca las consultas lentas o las transacciones largas que retienen conexiones.
FIELD_NOT_READABLE 400 Un filtro, orderBy, fields, select de agregado o groupBy nombra un campo que los roles de este cliente no pueden leer (access.read), una ruta anidada o una ordenación de agregado nombra una relación que no pueden leer, o una operación de campo ($inc, $push, …) apunta a uno, donde un límite rechazado revelaría el valor almacenado. Un campo que ninguna respuesta puede contener debe ser uno que ninguna consulta pueda interrogar, o el valor sería legible predicado a predicado. Un filtro a través de una relación (author.salary) y una ordenación de agregado sobre el campo de una relación (max(staff.salary)) se juzgan por la regla del destino. details.violations nombra cada campo. Un campo oculto con excludeFromApi responde como si no existiera: un filtro, orderBy, fields, include, select o groupBy de agregado, o vector_search que lo nombre recibe exactamente la respuesta de un nombre mal escrito (UNKNOWN_FILTER_FIELD, UNKNOWN_ORDER_BY_FIELD, UNKNOWN_FIELD, UNKNOWN_RELATION, UNKNOWN_AGGREGATE_FIELD o UNKNOWN_VECTOR_PROPERTY), y ninguna respuesta de campo desconocido lista alguno. Elimina el campo de la consulta o adquiere el rol. Consulta Field access.
FIELD_NOT_WRITABLE 400 El cuerpo establece un campo que los roles de este cliente no pueden escribir (access.write). Rechazado en lugar de descartado: una escritura que descarta un campo reportaría éxito para una edición que no ocurrió. El mismo código rechaza una escritura a través de un padre que establece una relación que el cliente no puede escribir, y una actualización que da un valor a un campo softDelete: solo un borrado lo marca. details.violations nombra cada campo. Elimina el campo o adquiere el rol. Un campo que nadie puede escribir responde con VALIDATION_EXCLUDED_FIELDS en su lugar.
HISTORY_UNAVAILABLE 503 Se rechazó una escritura en una colección con history: true porque no se pudo registrar su entrada de historial: la base de datos no tiene la tabla rebase.entity_history o, en el caso de openRebase y rebase console, no tiene la función rebase.record_history. Ningún backend con historial ha arrancado sobre esta base de datos. No se ejecutó nada, callbacks incluidos, y las lecturas no se ven afectadas. Lo lanza openRebase, y lo responde un backend creado con provision: false. Arranca el backend una vez con el historial activado y provision: true (rebase dev lo hace) y reintenta.
IDEMPOTENCY_KEY_IN_PROGRESS 409 Una solicitud anterior con la misma Idempotency-Key todavía se está ejecutando. Reintenta una vez que termine.
IDEMPOTENCY_KEY_REUSED 422 Llegó la misma Idempotency-Key con un cuerpo diferente. Usa una nueva clave o envía el cuerpo original.
INVALID_AGGREGATE_FUNCTION 400 ?select= especificó una función que no es count, sum, avg, min ni max. Usa una de ellas; el mensaje las enumera.
INVALID_AGGREGATE_SELECT 400 Una entrada de ?select= no es fn(field), o se proporcionó una función distinta de count() sin campo. Escribe sum(total), count(), avg(score).
INVALID_AGGREGATE_WINDOW 400 offset, page u orderBy en una agregación sin groupBy, o un cursor en cualquier agregación. Una agregación sin agrupar es una fila, y un grupo no es una fila tras la que un cursor pueda continuar. Añade groupBy, o quítalos; pagina los grupos con offset o page. Consulta Agregaciones.
INVALID_BATCH_BODY 400 A una operación de /_batch le falta op, collection, values o id, nombra una colección que este backend no sirve, o reutiliza un nombre de ref. Consulta el mensaje; identifica la operación por su índice.
INVALID_BATCH_REF 400 Un { "$ref": "<name>.<field>" } no nombra ninguna operación anterior, apunta hacia adelante o solicita un campo que la fila referenciada no tiene. Solo se resuelven referencias hacia atrás. Asigna el nombre a la operación con ref antes de referenciarla.
INVALID_BULK_BODY 400 El cuerpo masivo no tiene la estructura esperada. Envía el array items documentado.
INVALID_CONFLICT_TARGET 400 El on_conflict / onConflict de un upsert nombra columnas sin garantía de unicidad, las nombra sin upsert: true, o se envía en una creación anidada, donde una fila encontrada pasaría al nuevo padre. De lo contrario, Postgres respondería 42P10 desde el interior de una transacción que ya ha realizado trabajo. También cualquier upsert en la colección de usuarios (auth), donde una creación y una actualización siguen reglas distintas. Declara validation: { unique: true } o un índice unique; el mensaje lista los destinos que sí existen. En la colección de usuarios, envíe un POST para crear y un PATCH para actualizar.
INVALID_COUNT 400 ?count= no es exact ni none. Rechazado en lugar de leerse como el valor por defecto: un ?count=nnone mal escrito pagaría el conteo que se quería omitir. Envía exact (el valor por defecto) o none. Consulta Omitir el conteo.
INVALID_CURSOR 400 El cursor after no se puede leer, o nombra un id de fila que no encaja con las columnas clave de la colección: se truncó, se volvió a codificar o se construyó a mano. Devuelve meta.nextCursor de la página anterior sin cambios. Consulta Paginación.
INVALID_DELETED_PARAM 400 ?deleted= no es include ni only. Rechazado en lugar de ignorado: un ?deleted=true mal escrito que ocultara silenciosamente todas las filas eliminadas parecería funcionar y respondería la pregunta opuesta. Envía include (activas y eliminadas) o only (solo eliminadas). Omítelo solo para filas activas.
INVALID_DISTINCT 400 ?distinct= no es true ni false. Envía uno de esos valores; también se aceptan 1 y 0.
INVALID_FIELD_OPERATION 400 Se usó un $inc / $push / $pull / $merge en un tipo de propiedad en el que no está definido, con un operando con formato erróneo, con dos operadores en un mismo campo, mal escrito, o en una creación, donde no hay un valor almacenado sobre el cual operar. Consulta Writing over REST; el mensaje nombra el campo.
INVALID_FILTER_FIELD 400 El filtro nombra una propiedad que esta colección no tiene. Comprueba la ortografía en la colección.
INVALID_FILTER_OPERATOR 400 El operador no es compatible con este tipo de propiedad — por ejemplo like en un número o una fecha. Consulta Querying data.
INVALID_FILTER_VALUE 400 Un valor de filtro no se puede leer como el tipo de la columna contra la que se comparó: ?id=eq.abc en una clave entera, una etiqueta que no está en el enum, una marca de tiempo inválida, un número fuera del rango del tipo. details.dbCode contiene el SQLSTATE. Envía un valor del tipo de la columna.
INVALID_HARD_PARAM 400 ?hard= no es true ni false. Cualquier otra cosa se rechaza en lugar de interpretarse como “no”: un error tipográfico que elimine de forma lógica cuando el cliente pidió purgar le haría creer erróneamente que los datos desaparecieron. Envía true o false.
INVALID_INCLUDE 400 ?include= está malformado: no es una lista de rutas válida o está anidado más allá de la profundidad máxima. Se responde en la frontera en lugar de escapar del driver como un 500. Consulta el mensaje; nombra la ruta problemática.
INVALID_INPUT 400 El cuerpo no superó la validación. Consulta el mensaje.
INVALID_LIMIT — Una suscripción en tiempo real solicitó un límite fuera del rango permitido. Se entrega como un marco ERROR de WebSocket, no como una respuesta HTTP. Reduce el límite.
INVALID_LOGICAL_GROUP 400 Un grupo ?or= / ?and= está malformado o anidado más allá de la profundidad permitida. Consulta el mensaje; muestra la regla de aplanado.
INVALID_OFFSET 400 ?offset= no es un número entero mayor o igual a 0. Envía un entero no negativo.
INVALID_ORDER_BY 400 ?orderBy= no es field, field:desc ni un array JSON de { field, direction }. Consulta el mensaje; muestra las tres sintaxis posibles.
INVALID_PAGE 400 ?page= no es un número entero mayor o igual a 1. Las páginas están basadas en 1, por lo que ?page=0 es un error en lugar de la primera página. Envía 1 o superior, o usa ?offset=.
INVALID_PARAM 400 Un parámetro de consulta está malformado. Consulta el mensaje.
INVALID_QUERY_BODY 400 Desde 0.25 El cuerpo de un POST …/query contiene un valor que la URL no habría podido llevar: una lista para un parámetro que la URL lee una sola vez (fields, limit, …), un objeto para un filtro, o un parámetro que también está en la URL. Escribe cada valor como lo hace la URL — una cadena, o una lista para un filtro repetido; where, include, orderBy y vector aceptan JSON. Consulta Consultas demasiado largas para una URL.
INVALID_VECTOR 400 ?vector= no es un array JSON de números. Envía [0.1,0.2,0.3].
INVALID_VECTOR_DISTANCE 400 ?vector_distance= no es cosine, l2 ni inner_product. Usa uno de esos tres.
INVALID_VECTOR_THRESHOLD 400 ?vector_threshold= no es un número. Envía un número.
INVALID_WHERE 400 ?where= no es un objeto JSON que asocie campos con condiciones. Envía {"status":["==","active"]}.
KEY_IMMUTABLE 400 Una actualización nombra la clave de la fila con un valor distinto del que la direcciona — en el cuerpo, o escrito por un beforeSave. Una fila no puede moverse a otra clave: todo lo que ocurre después de la escritura (la relectura, afterSave, el historial, el tiempo real) la direcciona por la clave que tenía. Se rechaza antes de que se ejecute ningún hook, sin que se escriba nada, en todas las puertas. details.violations nombra el campo. Crea la fila con la clave nueva y elimina esta. Enviar la clave que la fila ya tiene es válido.
MISSING_AGGREGATE_SELECT 400 La ruta de agregados se invocó sin ?select=. Añade uno, p. ej. ?select=count().
NO_COLLECTIONS 404 El proyecto no sirve colecciones: ninguna declarada en código y sin tablas de las que derivarlas. Desde 0.25 Cuando existen tablas pero la seguridad a nivel de fila está desactivada en ellas, el mensaje las nombra, con el SQL para activarla, y details.unprotectedTables las enumera; en la 0.24 dice que no hay tablas. Crea tablas (una migración, SQL o un archivo de colección más rebase db push) y reinicia.
NOT_FOUND 404 No hay fila con ese id en esa colección, o la seguridad a nivel de fila la oculta a este cliente. Verifica el id y luego las securityRules de la colección.
UNKNOWN_RELATION 400 / 404 ?include= nombra algo que no es una relación en la colección. El mismo código responde 404 cuando una ruta URL anidada nombra una relación, p. ej. /api/data/authors/1/posts donde authors no declara ninguna; allí la URL no nombra nada, por lo que es un “no encontrado” en lugar de una solicitud malformada. Comprueba el nombre de la relación: el mensaje lista las que tiene la colección. Una referencia inversa debe declararse en el padre para poder recorrerse.
ORDER_BY_FIELD_NOT_SORTABLE 400 La ordenación nombra una propiedad que no se puede ordenar. Ordena según una propiedad respaldada por una columna.
PAGE_WITH_OFFSET 400 ?page= se combinó con ?offset= — o page con offset en un find(), que el SDK cliente, el rebase.data en proceso y el cliente sin conexión rechazan con el mismo código antes de cualquier solicitud. Describen la misma ventana, y page solía ganar en silencio sobre un offset que quien llamaba nunca veía aplicado. Envía uno de los dos.
PAYLOAD_TOO_LARGE 413 El cuerpo excede el límite configurado. Envía menos datos o aumenta el límite.
READ_ONLY_TRANSACTION 409 Un callback afterRead intentó escribir. Una lectura con ámbito de solicitud se ejecuta en una transacción READ ONLY, por lo que ni el callback ni nada de lo que invoque puede escribir. Mueve la escritura fuera de la lectura: una tarea en segundo plano, o rebase.dataAsAdmin desde una tarea cron o función personalizada.
RELATION_HAS_NO_PIVOT 400 La escritura incluía un payload de enlace, pero la ruta no llega a su destino mediante un manyToMany que declare through.properties, por lo que no hay fila de unión donde ponerlo. Declara through.properties en la relación o elimina el payload de la escritura. Consulta Relations.
RELATION_MISCONFIGURED 500 Una relación no se resuelve contra el esquema registrado. La operación se rechaza en lugar de omitirse: descartarla reportaría éxito para una escritura que nunca ocurrió, o un vacío para filas que existen. Ejecuta rebase schema generate si el esquema generado es anterior al de la base de datos.
RELATION_NOT_UNLINKABLE 400 La relación no se puede desvincular desde este lado. Escribe desde el lado propietario.
RELATION_NOT_WRITABLE 400 La ruta anidada no es una relación escribible. Consulta Relations.
RELATION_PIVOT_UNSUPPORTED 400 La relación declara columnas de unión, pero este origen de datos no puede escribirlas. El enlace en sí sigue funcionando; solo falla el payload asociado. Comprueba las capacidades del driver.
RELATION_SOURCE_KEY_EMPTY 400 Una escritura de relación no tenía una clave de origen a la cual asociar el enlace. Guarda primero la fila padre.
RESULT_TOO_LARGE — Desde 0.25 Una sentencia enviada por el EXECUTE_SQL del socket en tiempo real — admin.executeSql desde un cliente, las lecturas de catálogo del panel de administración — devolvió más de 128 MB de filas, así que no se envió ninguna. Se entrega como un fotograma ERROR de WebSocket. Las ejecuciones de la propia consola SQL no se rechazan: muestran las primeras filas. Añade un LIMIT, o selecciona menos columnas, y lee el resultado por partes.
ROW_IN_TRASH 409 La clave de un upsert pertenece a una fila en la papelera (una fila con soft delete conserva su clave). Un upsert no escribe en una fila eliminada, en ninguna puerta: los upserts de REST ?on_conflict=, /bulk y /_batch, el SDK y el socket en tiempo real. No se escribió nada. Restaura la fila primero (una actualización que establece el campo de soft delete en null), o púrgala con ?hard=true y vuelve a hacer el upsert. Consulta soft delete.
SCHEMA_DRIFT 500 Una tabla o columna que el código espera no existe en la base de datos. rebase db push en desarrollo; vuelve a desplegar en un entorno administrado (tenant).
SCORE_CURSOR_UNSUPPORTED 400 Se combinó startAfter con orderBy: "_score". La relevancia se calcula por consulta en lugar de almacenarse, por lo que no puede servir de clave para un cursor. Pagina la relevancia con limit/offset, u ordena por una columna.
SQL_ERROR 400 La base de datos rechazó SQL escrito por una persona. Por el EXECUTE_SQL del socket en tiempo real es un fotograma ERROR con el mensaje de la base de datos. Desde 0.25 POST /api/admin/sql/csv lo responde antes de enviar nada del archivo: un error de sintaxis, una escritura (la descarga se ejecuta en solo lectura), más de una sentencia, o un rol que la conexión no puede asumir. Corrige el SQL. Una descarga acepta un solo SELECT, WITH … SELECT, TABLE o VALUES.
TENANT_IMMUTABLE 400 Una escritura movería una fila de un tenant a otro. Una fila no puede cambiar de tenant. details.violations nombra el campo. Crea la fila en el otro tenant y elimina esta, o escribe con un rol en tenant.bypassRoles.
TENANT_MISMATCH 400 La escritura especifica un tenant al que este cliente no pertenece; la base de datos también la rechazaría. Escribe en un tenant al que pertenezca el cliente, o autentícate como alguien que pertenezca a él.
TENANT_REQUIRED 400 La colección está restringida por tenant y este no puede inferirse: la solicitud no incluye ninguno o el cliente pertenece a varios. Envía el campo del tenant explícitamente, o autentícate como un cliente que pertenezca exactamente a uno.
TRANSACTION_ABORTED 500 Una sentencia en la transacción de la escritura falló y un callback capturó el error. Postgres ya había abortado la transacción, así que la escritura se revirtió y no se almacenó nada. Solo una creación, actualización o eliminación de context.data que la base de datos rechazó se deshace por sí sola y es segura de capturar. Deja que el fallo se lance, o haz la comprobación antes de ejecutar la sentencia. Consulta Semántica de transacciones.
UNKNOWN_FIELD 400 ?fields= nombra un campo que la colección no tiene. Comprueba la ortografía; el mensaje lista los campos válidos.
UNKNOWN_AGGREGATE_FIELD 400 Un agregado o groupBy nombra un campo que la colección no tiene. Comprueba la ortografía; el mensaje lista los campos válidos.
UNKNOWN_FILTER_FIELD 400 El filtro nombra un campo que esta colección —o el destino de una relación— no tiene, o uno oculto con excludeFromApi. Comprueba la ortografía; el mensaje lista los campos válidos.
UNKNOWN_FILTER_OPERATOR 400 El filtro nombra un operador que no existe. El mensaje lista todos los operadores.
UNKNOWN_MESSAGE_TYPE 400 Un fotograma del socket en tiempo real tiene un type que el servidor no gestiona. Se responde como un fotograma ERROR con el requestId de la solicitud, de modo que la solicitud se resuelve en lugar de agotar el tiempo de espera. Revisa el type del fotograma; el mensaje lo nombra.
UNKNOWN_ORDER_BY_FIELD 400 La ordenación nombra un campo que esta colección no tiene. Comprueba la ortografía; el mensaje lista los campos válidos.
PRECONDITION_FAILED 412 Un If-Match indicó una versión de la fila que ya no es la actual: alguien escribió en ella entre la lectura y esta escritura. No se escribió nada. Vuelve a leer la fila, reaplica el cambio y envía el nuevo ETag.
UNKNOWN_RESPONSE_FIELD 400 ?fields= solicita un campo que la colección no tiene. Comprueba la ortografía; el mensaje lista los campos conocidos.
UNKNOWN_VECTOR_PROPERTY 400 Una búsqueda vectorial especificó una propiedad que no es un vector en esta colección. El mensaje lista las propiedades vectoriales de la colección.
UNSUPPORTED_MEDIA_TYPE 415 El Content-Type no es aceptado por esta ruta. Envía el tipo que documenta la ruta.
UNSUPPORTED_OPTION — Se lanza, no se responde: una escritura a través del accesor en proceso (context.data en un callback, rebase.data en una función o cron) recibió ifMatch o idempotencyKey. Esa puerta no tiene comprobación de precondición ni almacén de idempotencia, así que la opción se rechaza antes de escribir nada, en lugar de ignorarse. Quita la opción ahí, o haz la escritura a través del cliente HTTP, que respeta ambas.
UNSUPPORTED_RELATION_FILTER 400 El filtro cruza una relación via, cuya ruta de join está definida en una sola dirección, por lo que no hay forma de correlacionar una subconsulta de vuelta. Filtra desde el lado propietario.
UNSUPPORTED_RELATION_FILTER_OPERATOR 400 El operador no está definido para ese campo: una relación sin columna en esta fila se filtra por pertenencia, y la coincidencia de patrones (like, ilike y sus negaciones) solo aplica a texto. Consulta el mensaje; lista lo que acepta el campo.
VALIDATION_CONSTRAINT 400 Un valor violó una regla de validation declarada en la propiedad: una longitud, un rango, un patrón, un campo obligatorio. Consulta el mensaje; nombra cada violación.
VALIDATION_EXCLUDED_FIELDS 400 El cuerpo escribe en una columna marcada como excludeFromApi, o access: { write: [] } (la misma regla, dos formas de escribirla). Estas son exclusivas del servidor: un hash de contraseña, un token de verificación. A diferencia de FIELD_NOT_WRITABLE, esta respuesta es la misma para todos los clientes, incluido admin. Elimina el campo. Consulta Field access.
VALIDATION_INVALID_VALUE 400 Un valor no coincide con su tipo de propiedad. Consulta el mensaje; nombra la propiedad.
VALIDATION_UNKNOWN_FIELDS 400 El cuerpo nombra un campo que la colección no tiene, incluido un argumento id en una colección indexada por otra cosa. Comprueba la ortografía; el mensaje lista los campos conocidos.
VECTOR_CURSOR_UNSUPPORTED 400 Se combinó un cursor (after / startAfter) con una búsqueda vectorial. Las filas se ordenan por una distancia calculada por consulta, que no puede servir de cursor, así que un listado vectorial no lleva nextCursor. Pagina las filas más cercanas con limit/offset.
WRITE_DENIED 403 Una regla de seguridad o política de seguridad a nivel de fila rechazó la escritura. Consulta las securityRules de la colección.

PG_<SQLSTATE> — una restricción que la base de datos rechazó

Sección titulada «PG_<SQLSTATE> — una restricción que la base de datos rechazó»

Una escritura que Postgres rechaza por una razón atribuible a los datos del cliente responde con el SQLSTATE en el código: PG_23505, PG_23503, etcétera. Se trata de una familia, no de una lista (Postgres define cientos de SQLSTATEs), pero solo dos clases llegan a utilizarse aquí, porque solo esas dos son responsabilidad del cliente:

  • clase 23, violación de restricción de integridad: un duplicado, una clave foránea que apunta a la nada, una columna NOT NULL dejada vacía;
  • clase 22, excepción de datos: un valor que el tipo de columna no puede admitir.

Todo lo demás —una conexión caída, una columna faltante, un problema de privilegios— es del servidor y se mantiene como un 500. Por lo tanto, code.startsWith("PG_") es una comprobación segura de que “la fila que envié era incorrecta”, y las cuatro a continuación son las que un cliente encuentra en la práctica. details.dbCode contiene el mismo SQLSTATE para todas ellas, y el mensaje nombra la restricción.

Código Estado Significado Qué hacer
PG_22P02 400 No se pudo leer un valor como el tipo de la columna (el gemelo del lado de escritura de INVALID_FILTER_VALUE). Envía un valor del tipo de la columna.
PG_23502 400 Una columna NOT NULL se dejó vacía. Envía el campo, o define un valor por defecto para la columna.
PG_23503 400 Una clave foránea apunta a una fila que no existe. Crea primero la fila de destino o corrige el id.
PG_23505 409 Se violó una restricción de unicidad. El mensaje indica la restricción. Usa un valor diferente o actualiza la fila existente.
Código Estado Significado Qué hacer
INVALID_LIST_OPTIONS 400 El maxResults de un listado de almacenamiento no es un número entero de al menos 1, o su pageToken no lo emitió el origen. Un tamaño de página menor que uno devolvía antes una página vacía con el mismo token, así que un bucle while (pageToken) nunca terminaba. Envía un maxResults positivo y devuelve nextPageToken sin cambios.
INVALID_STORAGE_BUCKET 400 El nombre del bucket está malformado. Revisa el nombre.
INVALID_STORAGE_KEY 400 La clave del objeto está malformada o escapa de su prefijo. Revisa la clave.
INVALID_TRANSFORM_OPTIONS 400 Los parámetros de transformación de imagen están fuera de rango o son contradictorios. Consulta Storage.
STORAGE_FILE_TOO_LARGE 413 La subida supera el maxSize declarado por la propiedad de destino. Se aplica en el servidor, no solo en el navegador. details contiene la propiedad, el límite y el tamaño real. Sube un archivo más pequeño o aumenta maxSize en la propiedad.
STORAGE_FILE_TYPE_REFUSED 400 El tipo del archivo subido no está en el acceptedFiles de la propiedad, ni en el allowedMimeTypes propio del origen de almacenamiento. details contiene la propiedad (o la lista del origen), la lista aceptada y el tipo de contenido enviado. Sube un tipo aceptado o amplía acceptedFiles / allowedMimeTypes.
STORAGE_MISCONFIGURED 502 El bucket de S3 o GCS con el que está configurado este origen no existe, o el proveedor rechazó las credenciales de este despliegue para él. El mensaje nombra el bucket; details.reason es NoSuchBucket o el rechazo del proveedor. Un bucket inexistente solía leerse como «archivo no encontrado» en cada archivo. Corrige el nombre del bucket (S3_BUCKET / GCS_BUCKET, __<KEY> para un origen con nombre) o los permisos de las credenciales.
STORAGE_NOT_CONFIGURED 501 / 503 No hay backend de almacenamiento configurado en este servidor, o ninguno es el predeterminado y la solicitud no nombra ningún origen; el mensaje nombra los orígenes que se sirven (501). Una subida reanudable cuyo origen desapareció antes de terminar es un 503. Configura S3, GCS o almacenamiento local, o nombra un origen con ?storageId=.
STORAGE_SCAN_INCOMPLETE 409 Desde 0.25 DELETE /api/admin/storage/orphans (rebase storage orphans --delete) no pudo leer todas las colecciones, así que un archivo que una de ellas nombra parecería sin uso. No se eliminó nada; details.unscanned nombra cada colección y por qué no se pudo leer. Corrige lo que impide leer esas colecciones y ejecútalo de nuevo.
STORAGE_SOURCE_NOT_CONFIGURED 501 El origen de almacenamiento está declarado pero no tiene credenciales aquí. Configura las variables de entorno de ese origen.
STORAGE_WRITE_FAILED 502 El backend de almacenamiento rechazó o interrumpió la escritura. Revisa sus propios logs y credenciales.
TRANSFORM_OVERLOADED 503 Hay demasiadas transformaciones de imagen en curso. Reintenta; considera colocar una CDN delante.
UNKNOWN_STORAGE_SOURCE 400 / 404 La solicitud especificó un origen de almacenamiento (?storageId=) que este proyecto no declara. Un bucket que este despliegue no atiende devuelve el mismo código con 404 en un listado, y en una subida, carpeta o subida reanudable a S3 o GCS (lo que falta es el store, y details nombra los buckets y orígenes que sí existen). Anteriormente, ambos se devolvían como “archivo no encontrado”, idéntico a una clave que simplemente no existe. Declara el origen en config/resources.ts, o consulta GET /api/storage/sources.
UPLOAD_LOCKED 423 El PATCH de una subida reanudable llegó mientras aún se estaba recibiendo otro fragmento de esa misma subida — casi siempre un cliente reintentando un fragmento que ya está en curso. Se rechaza en lugar de encolarse, como hace tusd. Pide el offset con HEAD /api/storage/tus/:id y continúa desde ahí; tus-js-client espera y reintenta por su cuenta. Consulta Subidas reanudables (TUS).
Código Estado Significado Qué hacer
FUNCTION_NOT_FOUND 404 No se sirve ninguna función con ese nombre, o sí se sirve, pero sus propias rutas no cubren la ruta posterior. A un cliente autenticado también se le indica qué sí se sirve; a uno anónimo no, porque esa lista es un inventario de cada endpoint personalizado. Si un archivo con ese nombre no pudo cargarse, el mensaje se lo indica a un cliente autenticado, nombrando el archivo: esa es la diferencia entre un error tipográfico y un despliegue roto. Un cliente anónimo recibe la respuesta simple de nombre desconocido, como con un nombre que no coincide con nada. Comprueba el nombre contra GET /api/functions, o el log de arranque para ver si un archivo no se cargó.
FUNCTION_TIMEOUT 504 El handler excedió su tiempo de espera. Sigue ejecutándose; no se puede cancelar desde aquí. Añade un AbortSignal a las llamadas salientes o aumenta REBASE_FUNCTIONS_TIMEOUT_MS.
FUNCTIONS_UPSTREAM_UNREACHABLE 502 Este proceso reenvía funciones por proxy a otro que no respondió. Comprueba que la unidad de funciones esté en ejecución.
Código Estado Significado Qué hacer
CRON_JOB_ALREADY_EXECUTING 409 Una activación manual de una tarea cron que ya se está ejecutando — en el proceso que respondió, o en otro que tiene el lease de ejecución de la tarea, como el worker detrás de un proceso api. No se ejecutó nada. La omisión queda en el historial de la tarea, y details.log es esa entrada; su línea nombra el proceso que ejecuta la tarea. Vuelve a intentarlo cuando esa ejecución haya terminado. Consulta Tareas cron.

Superficies de administración y edición de esquemas

Sección titulada «Superficies de administración y edición de esquemas»

Estos indican que una funcionalidad está desactivada o no configurada, en lugar de que la solicitud fuera errónea. Cada uno también se reporta en la ruta /status correspondiente con un 200, de modo que un panel pueda atenuar la funcionalidad en lugar de mostrar un error.

Código Estado Significado Qué hacer
ADMIN_SURFACE_UNAVAILABLE 501 Se invocó una superficie exclusiva para administradores en un servidor sin autenticación configurada, por lo que nada puede distinguir a un administrador de un desconocido. Configura auth.jwtSecret o pasa un AuthAdapter.
CONTRACT_UNAVAILABLE 404 El contrato del proyecto solo se sirve cuando la autenticación está configurada (describe cada tabla y relación). Configura la autenticación. /meta/schema-version siempre se sirve.
DEV_MAILBOX_UNAVAILABLE 501 No hay ningún buzón de desarrollo activo. El correo solo se captura cuando SMTP_HOST no está configurado y NODE_ENV no es producción. Desasigna SMTP_HOST en desarrollo o revisa la bandeja de entrada real.
INVALID_CHANGE 400 El cambio de esquema propuesto no está bien formado. Consulta el mensaje.
SCHEMA_CHANGE_FAILED 400 La aplicación de un cambio de esquema planificado falló por una razón no cubierta por códigos más específicos. Consulta el mensaje; es el fallo subyacente de forma literal.
SCHEMA_CHANGE_UNAPPLICABLE 400 El cambio es válido pero no se puede aplicar al esquema en su estado actual. Consulta el mensaje.
SCHEMA_EDIT_DIRTY_TREE 409 El repositorio tiene cambios no confirmados, por lo que la edición no pudo aplicarse de forma segura. Haz commit o stash y luego reintenta.
SCHEMA_EDIT_REFUSED 400 El editor de esquemas rechazó la edición. Consulta el mensaje; es el propio rechazo del editor.
SCHEMA_EDIT_REQUIRES_A_PERSON 403 Una clave de API u otra entidad no humana intentó aplicar un cambio de esquema. Inicia sesión como usuario o configura liveSchema.allowMachineApply.
SCHEMA_EDITING_NO_COLLECTIONS_DIR 501 La edición de esquemas en vivo necesita collectionsDir o liveSchema.repository, y este servidor se inició sin ninguno de los dos. Configura uno.
SCHEMA_EDITING_NO_REPOSITORY 503 La planificación funciona; no hay repositorio en el que hacer commit del cambio. Configura liveSchema.repository.
SCHEMA_EDITING_UNSUPPORTED 503 Este driver no puede planificar cambios de esquema. La edición en vivo está disponible en Postgres.
SCHEMA_EDITOR_BAAS_MODE 501 Aquí las colecciones se introspeccionan desde la base de datos, por lo que no hay archivos fuente para editar. Modifica el esquema mediante una migración.
SCHEMA_EDITOR_DISABLED 501 El editor de esquemas está desactivado para este servidor. Un bundle compilado siempre responde esto. Actívalo con schemaEditor. En un bundle, define REBASE_LIVE_SCHEMA_REPOSITORY para editar las colecciones a través de un repositorio — consulta Edición de esquemas en vivo.
SCHEMA_EDITOR_MISSING_DEPENDENCY 501 El editor de esquemas necesita ts-morph, que no está instalado. pnpm add -D ts-morph@28.0.0.
SCHEMA_EDITOR_NO_COLLECTIONS_DIR 501 El servidor no tiene collectionsDir, por lo que el editor no tiene dónde escribir. Configura collectionsDir.
SCHEMA_EDITOR_PRODUCTION 501 El editor está desactivado bajo NODE_ENV=production: los archivos de un servidor desplegado se reconstruyen a partir de tu repositorio en cada despliegue, por lo que una edición aquí se descartaría. Edita las colecciones en desarrollo y despliega, o configura liveSchema.repository para confirmarlas allí.
SQL_EXPORT_UNSUPPORTED 501 Desde 0.25 POST /api/admin/sql/csv no puede transmitir un resultado aquí: la base de datos de desarrollo en proceso (PGlite) tiene una sola conexión, y un cursor mantenido durante una descarga retendría detrás de él todas las demás consultas; o el origen de datos no tiene cursor SQL. Apunta DATABASE_URL a un Postgres propio (rebase dev --docker inicia uno), o añade un LIMIT y exporta las filas en pantalla.

Una ruta utiliza uno de estos cuando no aplica nada más específico.

Código Estado Significado Qué hacer
BAD_REQUEST 400 Malformada, y nada más específico aplica. Consulta el mensaje.
UNAUTHORIZED 401 No autenticado, o la credencial fue rechazada. Inicia sesión o refresca el token.
FORBIDDEN 403 Autenticado, pero no autorizado. Reintentar con la misma identidad no servirá.
CONFLICT 409 Un conflicto con el estado existente. Consulta el mensaje.
INTERNAL_ERROR 500 Algo falló en el servidor. El mensaje es genérico a propósito. Cita el requestId; el motivo está en los logs.
NOT_CONFIGURED 503 Una dependencia que necesita esta ruta no está configurada en este servidor. Consulta el mensaje.
SERVICE_UNAVAILABLE 503 No se pudo llegar a un servicio del que depende la solicitud: un bucket de S3 o MinIO, o un host al que una función hace fetch() y que rechaza la conexión o no se resuelve. El log del servidor nombra el host; la respuesta no. Una base de datos a la que no se puede llegar es DATABASE_UNAVAILABLE. Desde 0.25 Una conexión fallida a un servicio así responde con este código; en la 0.24 responde un 500 cuyo código es el error del socket (ECONNREFUSED), o INTERNAL_ERROR. Reintenta; comprueba los logs.

pnpm verify:docs falla cuando un código que el servidor puede emitir falta en estas tablas, cuando una tabla lista un código que nada puede emitir, cuando los estados de una fila no son exactamente aquellos con los que el código fuente emite el código, o cuando una familia de códigos como PG_<SQLSTATE> no tiene fila para un SQLSTATE con el que los clientes se topan. El paso es tooling/scripts/docs-verify/check-error-codes.mjs.

Se comprueba a sí mismo primero. El análisis lee los códigos a partir de TypeScript en lugar de hacerlo desde un servidor en ejecución, por lo que sus puntos ciegos son silenciosos por diseño: en una ocasión no pudo detectar un código pasado a través de un wrapper de una sola línea, o uno escrito tras un mensaje que contenía un ), y reportó que “cada código que el servidor puede emitir está documentado” sobre una página a la que le faltaban diecisiete de ellos. Por ello, el paso ejecuta un fixture exactamente con esas estructuras antes de leer esta página, y se niega a reportar nada si no es capaz de verlos.