# Troubleshooting — errores típicos y diagnóstico

## Errores de Twilio (códigos)

| Código | Mensaje | Causa real | Fix |
|---|---|---|---|
| `21656` | The Content Variables parameter is invalid | Hay `\n` en las variables, o JSON es array en vez de object, o emojis encoding mal | Sanitizar body (sin `\n`), usar `JSON_FORCE_OBJECT \| JSON_UNESCAPED_UNICODE`, usar `+` en vez de `array_merge` |
| `63013` | Template not approved by WhatsApp | Template recién creado que Meta no aprobó | Esperar aprobación o usar un template aprobado |
| `63016` | Outside 24h window | Cliente no escribió en 24h y querés mandar free-form | Usar template aprobado |
| `21617` | Message body required | Mandaste mensaje sin Body ni ContentSid | Asegurar uno de los dos |
| `21610` | Attempt to send to unsubscribed | El cliente bloqueó el número | Sacar de la lista |
| `21617` | The 'Body' parameter requires a value | Body vacío | Validar antes |

## Errores de creación de templates

| Mensaje de Meta | Causa | Fix |
|---|---|---|
| `Reply Title text cannot contain [_*~{}\n]` | Title de botón tiene variable `{{N}}` o caracter prohibido | Usar título fijo sin variables |
| `Buttons can't have any variables, newlines, emojis, or formatting characters` | Emojis en títulos de botones de template nuevo | Sacar emojis o esperar que Meta vuelva a ablandar política |
| `The message body can't have more than two consecutive newline characters, only have parameters, or have more than 10 emojis` | Body con regla violada (especificada en mensaje) | Ajustar body según mensaje específico |
| `Variables can't be at the start or end of the template` | Body es `{{1}}...` o `...{{1}}` | Agregar texto fijo antes Y después de la variable |
| `This template has too many variables for its length` | Variables son alto % del body | Agregar texto fijo |

## Errores de Claude

| Mensaje | Causa | Fix |
|---|---|---|
| `messages.N: user messages must have non-empty content` | Tool result vacío en el loop | Garantizar que cada tool devuelve al menos `{"error":"..."}` |
| `Overloaded` (529) | API saturada | Retry con backoff |
| `Invalid request: messages alternating` | Mensajes user/assistant fuera de orden | Validar historial antes de mandar |
| `Image format not supported` | Imagen rara | Validar MIME antes de base64 |

## Diagnóstico paso a paso

### "El cliente no recibe respuesta"

1. **¿Llegó al webhook?**
   ```bash
   grep '[WA_WEBHOOK] request from' /var/log/apache2/herrajes_error.log | tail
   ```
   Si no hay log → Twilio no llegó al server. Chequear webhook URL en Twilio Console, DNS, firewall.

2. **¿Claude respondió?**
   ```bash
   grep 'WA_LOOP' /var/log/apache2/herrajes_error.log | tail
   ```
   Buscar `stop_reason=end_turn`. Si no, ver iteraciones.

3. **¿Twilio aceptó el envío?**
   Buscar `enviarConBotones tplSid=... code=201` (queued OK). Si code != 2xx, error en envío.

4. **¿Llegó al cliente?**
   ```bash
   curl -X GET "https://api.twilio.com/2010-04-01/Accounts/$SID/Messages.json?To=whatsapp:%2B549..." \
     -u "$SID:$TOKEN" | jq '.messages[0:5] | .[] | {status, error_code, body}'
   ```
   Status puede ser: `queued` → `sent` → `delivered` → `read`. Si quedó en `failed` con `error_code: 63013` = template no aprobado.

### "El agente se vuelve loco/repite/no avanza"

1. **¿Cuántos mensajes tiene cargados?**
   ```sql
   SELECT COUNT(*) FROM whatsapp_conversaciones WHERE from_number = '+549...';
   ```
   Si > 30, hay acumulación. El reset automático no se disparó.

2. **¿El último user message fue interpretado bien?**
   ```sql
   SELECT role, content, created_at
   FROM whatsapp_conversaciones
   WHERE from_number = '+549...'
   ORDER BY id DESC LIMIT 10;
   ```

3. **Solución temporal**: limpiar el historial a mano.
   ```sql
   DELETE FROM whatsapp_conversaciones WHERE from_number = '+549...';
   ```

### "Mensaje llega con caracteres `?` o `�`"

Encoding UTF-8 roto en algún paso del pipeline PHP. Checklist:
- `preg_replace` con flag `/u` (Unicode)
- `json_encode` con `JSON_UNESCAPED_UNICODE`
- `mb_strtolower` en vez de `strtolower`
- Si pasás archivos JSON al curl, leerlos como `--data-binary @file.json` (no inline en bash de Windows, que rompe encoding).

### "Botones aparecen pero no tienen los emojis correctos"

Te pasó a vos con `??` en lugar de `💰`. Causa: el JSON con emojis se mandó vía bash de Windows (PowerShell/git-bash) que corrompe UTF-8. Re-crear el template leyendo el JSON desde archivo en lugar de inline.

## Logs útiles para activar

```php
error_log("[WA_WEBHOOK] request from=" . $_POST['From']);
error_log("[WA_WEBHOOK] campos_boton=" . json_encode($_POST_buttons));
error_log("[WA_WEBHOOK] from=$from cliente=$idCliente/$nombre");
error_log("[WA_LOOP] inicio msgs=" . count($historial));
error_log("[WA_LOOP] iter=$i stop_reason=$stop content_blocks=$n");
error_log("[WA_LOOP] ejecutando tool=$nombre");
error_log("[WA_LOOP] tool=$nombre resultado_len=" . strlen($json));
error_log("[WA_BOTONES] enviarConBotones tplSid=$sid code=$code");
error_log("[WA_BOTONES] error tplSid=$sid resp=$body");
```

Habilitarlos solo en producción crítica — generan bastante volumen.

## Comandos diagnósticos para tener a mano

```bash
# Ver últimos 30 mensajes WhatsApp
ssh server 'grep "WA_" /var/log/apache2/error.log | tail -30'

# Status de un mensaje específico
curl "https://api.twilio.com/2010-04-01/Accounts/$SID/Messages/MM....json" -u "$SID:$TOKEN" | jq

# Estado de aprobación de un template
curl "https://content.twilio.com/v1/Content/HX..../ApprovalRequests" -u "$SID:$TOKEN" | jq

# Listar todos tus templates
curl "https://content.twilio.com/v1/Content?PageSize=50" -u "$SID:$TOKEN" | jq '.contents | .[] | {sid, friendly_name}'
```
