Saltar al contenido principal
Todo error de la API de Driftless (ya sea que lo alcances por la CLI, el servidor MCP o directamente) vuelve como el mismo sobre JSON. Un agente debería ramificar según el code legible por máquina, no parsear el message humano.

El sobre

{
  "statusCode": 403,
  "code": "MISSING_HUMAN_IDENTITY",
  "message": "Merging into Knowledge requires owner/admin authority: your own session or an owned owner/admin key (an agent acting on your explicit request). A faceless agent (ownerless key / OAuth) cannot merge.",
  "request_id": "a1b2c3d4",
  "retryable": false,
  "endpoint": "POST /api/v1/workspaces/acme/topics/auth-flow/approve"
}
CampoSignificado
statusCodeEstado HTTP.
codeCódigo de error estable y legible por máquina (esta lista es solo aditiva).
messageLegible por humanos, accionable. Te dice cómo arreglarlo. Puede cambiar; no hagas match sobre él.
request_idId de correlación. Cítalo al reportar un problema.
retryabletrue solo para fallos transitorios genuinos (5xx). Un 4xx es una respuesta definitiva, así que reintentar no ayuda.
endpointEl método + la ruta que produjo el error.
retryable es honesto: la CLI reintenta un GET una vez ante un fallo transitorio, pero nunca reenvía una escritura, y nunca reintenta un 4xx. Si construyes tu propio cliente, haz lo mismo.

Por qué un code siquiera

Una entrada incorrecta no debería llegar al agente como un 500 opaco. Dos capas lo garantizan:
  1. La validación rechaza un enum inválido (status, visibility) con un 400 a nivel de campo antes de que toque la base de datos.
  2. Un traductor de errores de Postgres captura cualquier violación de restricción que se escape y la convierte en un 4xx codificado, nunca en un 500 genérico.
Después de esas dos, un 500 significa lo que debe: un bug real o una caída. Ese es también el único momento en que retryable es true.

Catálogo de códigos

Validación y entrada

codeEstadoCuándo
VALIDATION_FAILED422 / 400Un campo del cuerpo de la petición falló la validación (p. ej. status must be one of: draft, proposed, reviewed, …).
BAD_REQUEST400Una petición inválida genérica sin un código más específico.
INVALID_VALUE400Un valor viola una restricción CHECK de la base de datos.
INVALID_ID400Un identificador de ruta/cuerpo no es un UUID válido.
REQUIRED_FIELD400Faltaba un campo requerido.
FK_VIOLATION400Referencia un registro que no existe.
SECRET_DETECTED400Un campo de topic parecía una credencial (API key, token, clave privada) y la escritura se bloqueó. Quítala, o define allow_secrets: true (CLI --allow-secrets) para forzarla. El error enmascara la coincidencia; nunca repite el secreto.

Acceso e identidad

codeEstadoCuándo
UNAUTHORIZED401API key / token faltante o inválido. → driftless login --key <key>.
FORBIDDEN403Autenticado, pero sin permiso.
MISSING_HUMAN_IDENTITY403Un principal sin rostro (una key sin dueño, o un token OAuth sin un owner/admin detrás) intentó fusionar en Knowledge. Vuelve a emitir la key desde el dashboard para que lleve tu identidad, o ejecuta la fusión bajo un owner/admin.
INSUFFICIENT_ROLE403No tienes el rol de workspace para esta acción: solo un owner/admin puede aprobar. Pídele a uno que te promueva en Settings → Members.
NOT_FOUND404El recurso no existe (o es el borrador privado de otro miembro que no puedes ver, así que devolvemos 404, nunca 403).

Gobernanza y conflictos

codeEstadoCuándo
DUPLICATE409Ya existe un registro con estos valores.
DUPLICATE_TOPIC409Ya existe un topic con ese slug en el workspace.
VERSION_CONFLICT409expected_version no coincidió: alguien escribió desde que leíste. Vuelve a leer y reintenta.
CONFLICT409Un conflicto de estado genérico.
PROTECTED_RESOURCE403Un recurso protegido/por defecto no puede modificarse ni eliminarse.
RATE_LIMITED429Demasiadas peticiones. Reduce el ritmo.

Servidor

codeEstadoCuándo
INTERNAL500Un fallo inesperado. retryable: true. Cita request_id si persiste.

Observabilidad

Cada error capturado también se emite a PostHog (api_error del lado del servidor, cli_command_error desde la CLI) con code, status_code y endpoint como propiedades, de modo que la superficie de errores es un único mapa consultable, segmentable por tipo y endpoint en vez de texto libre.