# Manejo de errores

> Cada error de Connect llega con un código estable, una acción sugerida y un correlativo de soporte. Esta guía enseña a manejarlos; el catálogo completo vive en la referencia.



Todo error llega con la misma forma, pensada para que un humano o un agente sepan el paso siguiente
sin adivinar:

```json
{
  "error": {
    "code": "validation_error",
    "message": "'sii.rcv.consultar' requiere una conexión concreta.",
    "suggested_fix": "Pasa el connectionId de la conexión de 'sii' (MCP: campo 'connectionId' de execute; REST: header 'X-Connect-Connection'). Lístalos con la tool 'conexiones.estado.consultar'.",
    "request_id": "req_5tYw2nRk88Ma"
  },
  "meta": { "request_id": "req_5tYw2nRk88Ma", "tool_id": "sii.rcv.consultar", "plane": "action", "latency_ms": 12, "audit_status": "recorded" }
}
```

## Las reglas [#las-reglas]

* **Decide por `code`, nunca por el texto.** `message` puede cambiar; los códigos no.
* **`suggested_fix` está escrito para ejecutarse.** Si tu agente recibe el error crudo, ya sabe qué
  hacer.
* **`request_id` correlaciona con la [bitácora](/docs/conceptos/bitacora)** y es lo primero que pedirá
  soporte. Guárdalo en tus logs.
* **Reintenta solo lo reintentable.** Cada código declara su semántica de reintento en el
  [catálogo](/docs/referencia/errores). El SDK reintenta GET por su cuenta; los `execute` (POST) nunca
  se reintentan solos: una acción regulada reintentada a ciegas se ejecuta dos veces.

## El handler de referencia [#el-handler-de-referencia]

```ts
import { ConnectError } from "@emisso/connect";

try {
  await connect.tools.sii.rcv.consultar(input, { connectionId });
} catch (err) {
  if (!(err instanceof ConnectError)) throw err;
  switch (err.code) {
    case "connection_credential_required":
      // La clave cambió o fue revocada: pide reconectar con un enlace nuevo.
      return pedirReconexion(connectionId);
    case "connection_sync_in_progress":
      // Reintentable: espera y vuelve a intentar.
      return reintentarLuego();
    default:
      log.error({ code: err.code, requestId: err.requestId }, err.suggestedFix);
      throw err;
  }
}
```

## Los errores que vas a ver primero [#los-errores-que-vas-a-ver-primero]

| Código                           | HTTP | Reintentable | Qué significa y qué hacer                                                                                                                                  |
| -------------------------------- | ---- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `connection_credential_required` | 428  | no           | La conexión no tiene credencial viva (clave cambiada o revocada). Enlace con `modo: "reconectar"`.                                                         |
| `connection_sync_in_progress`    | 409  | sí           | Ya corre un sync de ese período. Espera y reintenta.                                                                                                       |
| `scope_not_granted`              | 403  | no           | La API key no tiene el scope de la tool. Revísala en [/api-keys](https://connect.emisso.ai/api-keys). Scopes vacíos significan cero autoridad, no comodín. |
| `validation_error`               | 400  | no           | El input no cumple el schema; `error.details` trae el detalle campo a campo. También cubre el `connectionId` ausente del ejemplo de arriba.                |
| `tool_not_found`                 | 404  | no           | Ese id no existe para tu organización. También cubre conectores no habilitados.                                                                            |
| `connection_session_pending`     | 409  | sí           | Solo BICE: el portal exige navegador y la sesión aún no se acuña. Corre la sincronización de esa conexión o espera la programada.                          |
| `rate_limited`                   | 429  | sí           | Superaste un límite. Respeta el backoff y reintenta.                                                                                                       |
| `upstream_error`                 | 502  | sí           | El SII o el banco fallaron al otro lado. Reintentar suele bastar.                                                                                          |

El catálogo completo, con los 34 códigos agrupados por dominio y una acción por cada uno, está en la
[referencia de errores](/docs/referencia/errores).

## Próximos pasos [#próximos-pasos]

* [Catálogo de errores](/docs/referencia/errores): los 34 códigos con qué significa y qué hacer.
* [Webhooks](/docs/operar/webhooks): los fallos de sincronización también llegan como evento firmado.
* [Límites y planes](/docs/operar/limites): los números detrás de 429 y 402.
