# Códigos de error: Alarmas del vigía de canales

> El vigía (`src/channels/ops/alarms/`) revisa cada pocos minutos el receptor de Meta, el ingreso, los salientes y la DLQ. Cada alarma se levanta una vez (`RAISED`), se repite cada 15 min mientras siga (`REPEAT`) y se resuelve sola cuando deja de verse (`RESOLVED`). Severidad `critical`/`high` sale como error en Render; `medium` como aviso.

**Cómo se detecta (toda la familia):** Render: buscar `[channels.alarm] RAISED code=<CÓDIGO>` (trae severity, key, count y detail sin datos de clientes). En vivo, la operación de canales lista las alarmas activas y permite forzar una revisión (solo plataforma).

**Qué hacer (toda la familia):** Lee el `detail` de la línea: dice qué revisar. Cada ficha tiene el paso concreto. Una alarma de prueba (`test=true`) no es un incidente y se resuelve sola a los 5 min.

Lo que un código no dice lo hereda de la familia.

## `DLQ_NOT_EMPTY`

- **Tipo:** alarma · **HTTP:** — · **Estado:** vigente
- **Severidad:** alta
- **Qué significa:** Una cola de mensajes muertos (DLQ de SQS) tiene mensajes: algo falló todas sus veces.
- **Qué hacer:** Ver qué cola dice `key`, leer los mensajes de la DLQ y reprocesarlos cuando la causa esté arreglada (skill `test-aws-workflows` para las de workflows).

## `FACTS_UNCLAIMED`

- **Tipo:** alarma · **HTTP:** — · **Estado:** vigente
- **Severidad:** crítica
- **Qué significa:** Hechos de canal (mensajes, estados) que nadie reclamó: ni se mostraron en el chat ni dispararon workflows.
- **Causa típica:** Ningún consumidor quedó como ganador para ese hecho: la cuenta no está en el camino nuevo ni en el viejo, o un consumidor falló.
- **Qué hacer:** Revisar los interruptores de la cuenta dueña (`key`) y los consumidores del bus.

## `INGRESS_QUARANTINE_NEW`

- **Tipo:** alarma · **HTTP:** — · **Estado:** vigente
- **Severidad:** media
- **Qué significa:** Entró algo nuevo a la cuarentena de ingreso en la última hora (un hecho que no se pudo asignar a una cuenta o entidad).
- **Qué hacer:** Revisar el mapa de cuentas: la cuenta de Meta tiene que existir en la entidad. `key` dice el motivo de la cuarentena.

## `INGRESS_RECEIPTS_STUCK`

- **Tipo:** alarma · **HTTP:** — · **Estado:** vigente
- **Severidad:** alta
- **Qué significa:** Hay recibos de ingreso sin terminar hace más de 30 s. El barredor los reprocesa desde el crudo; si sigue, el worker está trabado.

## `INGRESS_SILENCE`

- **Tipo:** alarma · **HTTP:** — · **Estado:** vigente
- **Severidad:** alta
- **Qué significa:** Un objeto de canal (número o página) que debería estar recibiendo por Boost no tiene recibos hace más del umbral (10 min en horario de oficina de Guatemala), o no tuvo ninguno en 7 días (`count=-1`).
- **Causa típica:** Casi siempre es ruido, por tres razones medidas el 30/09/2026: (1) toda cuenta con ingreso `boost` se vigila aunque tenga poco tráfico, con el mismo umbral fijo, así que un número o una página tranquila alarma siempre (hubo WABAs con 2 y 6 recibos en 7 días marcando 1000 min de silencio); (2) cada proceso guarda sus alarmas en memoria, así que en cada deploy, reinicio o instancia vuelve a salir `RAISED` todo lo que ya estaba; (3) `count=-1` es un objeto sin ningún recibo en 7 días: al 30/09 la cuenta de Instagram con ingreso `boost` no tiene recibos `instagram:` en absoluto. Es real solo si un objeto con tráfico normal deja de recibir: suscripción de la app caída, override del número apuntando a otro lado o receptor caído.
- **Cómo detectarlo:** Render: `[channels.alarm] RAISED code=INGRESS_SILENCE key=<objeto> count=<min>`; el `detail` dice hace cuántos minutos. Para separar ruido de corte real: `yarn -s boost ops logs "INGRESS_SILENCE" --horas 6` y ver si el mismo `key` se repite con `count` que solo crece (cuenta tranquila) o si objetos que suelen tener tráfico alto aparecen todos juntos (corte).
- **Qué hacer:** Mandar un mensaje de prueba al número o página: si entra, era silencio real y no hay nada que hacer. Si no entra, revisar `PAGE_SUBSCRIPTION_MISSING` / `PHONE_OVERRIDE_MISSING` y el receptor. Para `count=-1` en Instagram, revisar la suscripción de la app al objeto `instagram` y que la llave del recibo coincida con `external_channel_id`. La corrección del vigía está propuesta en «Ruido conocido» (arriba) y no está hecha.

## `OUTBOUND_QUEUED_STALE`

- **Tipo:** alarma · **HTTP:** — · **Estado:** vigente
- **Severidad:** alta
- **Qué significa:** Mensajes de la salida directa en `queued` hace más de 2 min: el envío no terminó.

## `PAGE_SUBSCRIPTION_MISSING`

- **Tipo:** alarma · **HTTP:** — · **Estado:** vigente
- **Severidad:** crítica
- **Qué significa:** La app de Boost no estaba suscrita a los webhooks de una página. El vigía intenta re-suscribirla solo.
- **Qué hacer:** Si el `detail` dice que se re-suscribió, recuperar el hueco (mensajes que no entraron) leyendo las conversaciones de la página en Meta. Si la re-suscripción falló, reconectar la página.

## `PHONE_OVERRIDE_MISSING`

- **Tipo:** alarma · **HTTP:** — · **Estado:** vigente
- **Severidad:** crítica
- **Qué significa:** El override de webhook del número de WhatsApp no apunta al receptor de Boost. El vigía intenta re-aplicarlo solo.
- **Qué hacer:** Si no se pudo re-aplicar, revisar el número en Meta y la cuenta en Configuración → Canales.

## `RECEIVER_SIGNATURES_REJECTED`

- **Tipo:** alarma · **HTTP:** — · **Estado:** vigente
- **Severidad:** crítica
- **Qué significa:** El receptor está rechazando webhooks de Meta porque la firma no cuadra (responde 403).
- **Causa típica:** `META_APP_SECRET` del receptor no es el de la app que manda los webhooks (rotación o variable equivocada).
- **Qué hacer:** Revisar `META_APP_SECRET` del receptor en Render (solo el nombre; el valor lo pone plataforma).

## `RECEIVER_SPILLED_UNQUEUED`

- **Tipo:** alarma · **HTTP:** — · **Estado:** vigente
- **Severidad:** alta
- **Qué significa:** Hay sobres en `meta/unqueued/` del derrame: el receptor los guardó pero no los encoló.
- **Qué hacer:** Correr la recuperación del derrame para encolarlos.

## `RECEIVER_STORE_FAILED`

- **Tipo:** alarma · **HTTP:** — · **Estado:** vigente
- **Severidad:** crítica
- **Qué significa:** El receptor no pudo guardar el crudo de un webhook y le respondió 503 a Meta (Meta reintenta).
- **Qué hacer:** Revisar el almacenamiento del receptor. Mientras Meta reintente no se pierde nada, pero no por siempre.

## `RECEIVER_UNHEALTHY`

- **Tipo:** alarma · **HTTP:** — · **Estado:** vigente
- **Severidad:** crítica
- **Qué significa:** El health del receptor de Meta falla varias veces seguidas.
- **Causa típica:** El receptor está caído o no llega a su almacenamiento. En páginas e Instagram, una hora de fallas hace que Meta desuscriba la app.
- **Qué hacer:** Revisar el servicio del receptor en Render y su almacenamiento. Si ya pasó una hora, revisar después `PAGE_SUBSCRIPTION_MISSING`.

## `WATCHDOG_CHECK_FAILED`

- **Tipo:** alarma · **HTTP:** — · **Estado:** vigente
- **Severidad:** media
- **Qué significa:** Una de las revisiones del vigía falló (no pudo leer la base, la cola o Meta). No es un incidente del canal en sí, pero mientras dure esa revisión no vigila.
