# Gestión de errores

> OpenWAFError lleva el estado HTTP, el código de error de la API, el campo y el cuerpo decodificado; cómo tratar los conflictos de versión y los fallos del cliente.

Cada error de la API, una respuesta con estado 400 o superior, se lanza como `OpenWAFError`:

| Propiedad | Significado |
|---|---|
| `status` | Estado HTTP. `0` cuando la petición no obtuvo respuesta de la API (ver abajo). |
| `code` | El código de error de la API, como `not_found`, `invalid`, `forbidden`, `reason_required` o `version_conflict`. `http_<estado>` cuando la respuesta no trae código. |
| `message` | El mensaje de la API. |
| `field` | En los errores de validación, el campo que indica la API, cuando lo indica. |
| `body` | El cuerpo del error decodificado, con los datos adicionales como `current_version` o `hostnames`. |

Los códigos son los de la API; los propios de las escrituras versionadas están en [Errores del control de cambios](https://developers.openwaf.dev/es/change-control/errors/).

## Conflictos de versión

Una escritura enviada con una versión esperada que ya no es la actual falla con estado `412` y código `version_conflict`, y no aplica nada. `body.current_version` es la versión que tiene ahora la zona. Vuelve a simular, revisa el plan nuevo y confirma con la versión nueva; no reintentes a ciegas.

**TypeScript**

```ts
import { OpenWAFError } from "./openwaf.ts";

try {
  await owf.createRecord({ zone: zoneId, body: record }, { reason, ifMatch: plan.from_version! });
} catch (err) {
  if (err instanceof OpenWAFError && err.code === "version_conflict") {
    const { current_version } = err.body as { current_version: number };
    console.log(`la zona ya va por la versión ${current_version}: vuelve a simular`);
  } else {
    throw err;
  }
}
```
**Python**

```py
from openwaf import OpenWAFError

try:
    owf.create_record(zone=zone_id, body=record, reason=reason, if_match=plan["from_version"])
except OpenWAFError as e:
    if e.code == "version_conflict":
        print("la zona ya va por la versión %d: vuelve a simular" % e.body["current_version"])
    else:
        raise
```
`str(e)` es `version_conflict (HTTP 412): the configuration changed: the current version is 9`.


## Errores de validación

`invalid` (estado 422) significa que la API ha rechazado un valor; `field` lo indica cuando puede, como `content` o `records[0].ttl`. Una simulación falla igual que la escritura real, así que simular es una forma segura de validar datos.

## Fallos del cliente

| Fallo | TypeScript | Python |
|---|---|---|
| No hay token configurado | `OpenWAFError`, estado 0, código `no_token` | Igual |
| No se puede averiguar la organización (pasa `org`) | `OpenWAFError`, estado 0, código `org_unresolved` | Igual |
| No hay `fetch` disponible | `OpenWAFError`, estado 0, código `no_fetch` | — |
| No se puede contactar con la API | El error que lanza `fetch` (un `TypeError`), sin envolver | `OpenWAFError`, estado 0, código `unreachable` |
| Cancelado con `signal` | El `AbortError` que lanza `fetch` | — |

## Reintentos

Los SDK no reintentan. Las lecturas y las simulaciones se pueden reintentar sin riesgo tras un error de red o un `5xx`. Una escritura enviada con `ifMatch`, también: si el primer intento se aplicó, el reintento falla con `version_conflict` en vez de aplicar el cambio dos veces.
