Códigos de error del relay de notificaciones (push-relay)
Los responde el relay central de notificaciones (W3-RLY-01, sección 6 de ARCHITECTURE) como
application/problem+json (code, title, status, detail opcional). El detail nunca
contiene tokens de dispositivo, claves, datos de quien llama ni contenido de la carga. La prueba
every_relay_code_is_documented en relay/crates/push-relay-core/src/error.rs mantiene
sincronizadas esta página y el código.
Una notificación que llegó a APNs o FCM nunca es un error: POST /v1/push responde 200 con un
result de accepted, invalid_token, rejected o failed, además del estado y el código de
razón del proveedor. Los códigos de abajo son para solicitudes que el relay rechazó antes de enviar
nada. Cada notificación rechazada libera su clave de idempotencia, así que el PBX puede reintentarla
con la misma clave.
Resultados de notificaciones (W3-RLY-02)
Cada notificación que el relay envía al proveedor termina en exactamente un result. Ese resultado
se devuelve en la respuesta de la notificación, se guarda 30 días en relay_deliveries, se puede
consultar después con POST /v1/receipts/query y se cuenta en
mpbx_relay_pushes_total{platform,kind,result}. upstream_status y upstream_reason son los del
último intento.
result | Significado | Respuestas típicas del proveedor | Reintentada por el relay | Qué hace el PBX (W3-PUSH-01) |
|---|---|---|---|---|
accepted | APNs o FCM aceptaron la notificación para entrega. Todavía no es prueba de que el teléfono la recibió: eso lo indica el acuse (delivered_at). | APNs 200; FCM 200 | — | Seguir timbrando; registrar el id de la notificación; marcar como entregada cuando llegue un acuse. |
invalid_token | El token del dispositivo ya no es válido. El relay marca el dispositivo como inválido; las notificaciones siguientes responden RELAY-DEVICE-INVALID hasta que la app registre un token nuevo. | APNs 400 BadDeviceToken, 400 DeviceTokenNotForTopic, 410 Unregistered; FCM 404, UNREGISTERED, SENDER_ID_MISMATCH; FCM INVALID_TOKEN_FORMAT (verificación local) | no | Marcar el dispositivo como degraded, avisar al usuario y timbrar los demás dispositivos. |
rejected | APNs o FCM rechazaron la notificación por otra razón permanente (carga, tópico o nuestras credenciales tras una renovación). Reintentar la misma notificación no puede ayudar. | APNs 400 por otras razones, 403 ExpiredProviderToken / InvalidProviderToken dos veces; FCM 400 INVALID_ARGUMENT, 401 dos veces, THIRD_PARTY_AUTH_ERROR dos veces; locales del relay provider_token, oauth_sign, oauth_failed (4xx) | token del proveedor u OAuth renovado una vez | Timbrar los demás dispositivos; los operadores ven mpbx_relay_pushes_total{result="rejected"}. |
failed | Fallas transitorias hasta agotar el presupuesto de reintentos (3 intentos, 5 s para llamadas, 15 s para notificaciones). | 429, 500, 503; FCM QUOTA_EXCEEDED, UNAVAILABLE, INTERNAL; locales del relay connect, timeout, oauth_connect, oauth_body | sí, con espera exponencial con variación aleatoria y Retry-After | Reintentar dentro de la ventana de timbrado con la misma clave de idempotencia y timbrar en paralelo los demás dispositivos. |
upstream_reason siempre es un código de razón del proveedor o del relay de esta tabla (máximo 64
caracteres), nunca contenido de la carga.
Acuses de entrega (W3-RLY-02)
La app confirma cada notificación con POST /v1/receipts {push_id, receipt} (campos de la carga p
y r). Un acuse válido responde 204, también cuando es una repetición (se registra una sola vez).
El PBX lee resultados y acuses con POST /v1/receipts/query {push_ids} firmado (máximo 200 ids);
los ids de otras instancias, los ids desconocidos y los ids con más de 30 días de retención no
aparecen en la respuesta.
| Código | HTTP | Significado | Qué hacer |
|---|---|---|---|
RELAY-AUTH-MISSING | 401 | Falta un encabezado de firma (x-mpbx-instance o x-mpbx-public-key, x-mpbx-timestamp, x-mpbx-nonce, x-mpbx-signature) o está mal formado. | Usar mpbx-push-relay-client, que firma cada solicitud (mpbx-relay-sig-v1). |
RELAY-AUTH-SKEW | 401 | La marca de tiempo de la solicitud está a más de 300 s del reloj del relay (el detalle indica la hora del relay), o es anterior a la época de repetición del relay: la solicitud se firmó antes de una conmutación de región o de un reinicio de Valkey (W10-RLY-01). | Corregir el reloj del host del PBX (NTP). Después de una conmutación, volver a firmar la solicitud (el PBX lo hace en cada reintento). |
RELAY-AUTH-REPLAY | 401 | Esta instancia ya usó el nonce en los últimos 10 minutos: solicitud repetida o duplicada. | Enviar cada solicitud con un nonce nuevo (el cliente lo hace). Al reintentar una notificación se usa la misma clave de idempotencia, no el mismo nonce. |
RELAY-AUTH-INVALID | 401 | La firma no se verifica, o el id de la instancia es desconocido (por diseño no se distinguen ambos casos). | Verificar que MPBX_RELAY_INSTANCE_KEY sea la clave que se registró. Si la clave se reemplazó sin una rotación, registrar de nuevo (la clave nueva obtiene un id de instancia nuevo); para rotar sin perder los dispositivos, usar POST /v1/instances/rotate-key. Una rotación de clave cuya prueba de la clave nueva no se verifica también responde este código. |
RELAY-ENROLL-CODE-REQUIRED | 403 | Este relay acepta registros solo con un código de activación (MPBX_RELAY_ENROLLMENT=code_required). | Solicitar un código de activación a MonoPbx y ejecutar la activación manual. |
RELAY-ENROLL-CODE-INVALID | 403 | El código de activación es desconocido, ya se usó o venció. Los códigos son de un solo uso. | Solicitar un código nuevo (push-relay activation-code create en el relay). |
RELAY-ENTITLEMENT-EXPIRED | 403 | La licencia se revocó y terminó su periodo de gracia de 30 días. Las notificaciones se rechazan de forma explícita, nunca se descartan en silencio. | Contactar a MonoPbx. Durante el periodo de gracia las notificaciones siguen fluyendo y cada respuesta incluye x-mpbx-entitlement: grace; ends=.... |
RELAY-BAD-REQUEST | 400 | El cuerpo no es JSON válido para el endpoint, o un campo no es válido (por ejemplo, una notificación de llamada sin call_uuid, un token con formato incorrecto o una notificación de iOS sin el token correspondiente). El detalle indica el campo. | Corregir la solicitud. |
RELAY-BODY-TOO-LARGE | 413 | El cuerpo supera los 16 KiB. | Las solicitudes son pequeñas; es un error del cliente. |
RELAY-DEVICE-NOT-FOUND | 404 | El push_ref no existe para esta instancia (puede pertenecer a otra instancia, lo cual no se revela), o el endpoint no existe. | Registrar el dispositivo de nuevo y guardar el push_ref nuevo. |
RELAY-DEVICE-INVALID | 410 | APNs o FCM informaron antes que el token del dispositivo no es válido, así que el relay dejó de usarlo. | La app debe enviar un token nuevo; registrarlo de nuevo (el mismo device_id conserva el push_ref). |
RELAY-DEVICE-LIMIT | 409 | La instancia ya tiene el máximo de dispositivos registrados (20 000 por omisión). | Eliminar los dispositivos que ya no existen (DELETE /v1/devices/{push_ref}). |
RELAY-IDEMPOTENCY-CONFLICT | 409 | La clave de idempotencia ya se usó con un cuerpo de solicitud distinto. | Usar una clave nueva para una notificación distinta (el cliente usa <call_uuid>:<kind>:<push_ref>). |
RELAY-IDEMPOTENCY-IN-FLIGHT | 409 | Todavía se está enviando una solicitud con la misma clave de idempotencia. | Esperar la primera respuesta; reintentar después de Retry-After. |
RELAY-RATE-LIMITED | 429 | Se superó la tasa de notificaciones por instancia (20/s, ráfaga de 200), las operaciones sobre dispositivos (600/min) o los intentos de registro (10/min por dirección). | Reintentar después de Retry-After. |
RELAY-QUOTA-DAILY | 429 | Se alcanzó el límite diario estricto por instancia (100 000 notificaciones por día UTC por omisión). | Reintentar después de Retry-After (el día UTC siguiente) o contactar a MonoPbx. |
RELAY-QUOTA-DEVICE | 429 | Más de 30 notificaciones a un dispositivo en un minuto. | Reintentar después de Retry-After; revisar en el PBX si hay un bucle de notificaciones. |
RELAY-PLATFORM-UNAVAILABLE | 503 | El relay no tiene credenciales de APNs (iOS) ni de FCM (Android) configuradas, ni la clave de cifrado de Web Push (MPBX_RELAY_WEB_PUSH_KEK_PATH, navegadores). También lo imprime push-relay serve cuando no puede cargar una clave configurada. | Operador: configurar MPBX_RELAY_APNS_* o MPBX_RELAY_FCM_* (docs/guides/push-relay.md). |
RELAY-WEB-ENDPOINT-REFUSED | 422 | El relay no enviará notificaciones al endpoint de Web Push de un registro de dispositivo web (W6-RLY-WEB, protección SSRF): no es https, usa una dirección IP en lugar de un nombre de host, incluye información de usuario o un puerto distinto de 443 en la URL, el host no es uno de los servicios de notificación conocidos (MPBX_RELAY_WEB_PUSH_HOSTS), o la clave de suscripción tiene un tamaño incorrecto. La misma verificación se repite antes de cada notificación, y un host que se resuelve a una dirección privada, de loopback o de enlace local se rechaza en ese momento. | PBX: informar al usuario que el servicio de notificaciones de este navegador no es compatible (las llamadas siguen timbrando mientras MonoPbx esté abierto). Operador: agregar el sufijo de host del servicio de notificaciones a MPBX_RELAY_WEB_PUSH_HOSTS solo si es un servicio público real. |
RELAY-RECEIPT-INVALID | 401 | El token del acuse no corresponde al id de la notificación, o el id no es un id de notificación del relay. Cada token está ligado a una sola notificación. | App: enviar los valores p y r de la notificación exactamente como se recibieron. |
RELAY-RECEIPT-EXPIRED | 410 | La notificación tiene más de 25 horas; ya no se puede confirmar. | Nada; descartar la confirmación. |
RELAY-RECEIPTS-UNAVAILABLE | 503 | El relay no tiene clave de acuses (MPBX_RELAY_RECEIPT_KEY_PATH), así que las notificaciones no incluyen token de acuse. | Operador: configurar la clave (docs/guides/push-relay.md). El PBX considera accepted como el último estado conocido. |
RELAY-UNAVAILABLE | 503 | La base de datos del relay o Valkey no están disponibles. | Reintentar; mientras tanto el PBX sigue timbrando los dispositivos activos (ARCHITECTURE 11.3). |
RELAY-INTERNAL | 500 | Error inesperado del relay (se registra en el relay). | Reintentar; reportar si persiste. |