Los errores del resolver llegan con HTTP 200
Esto es lo más importante que debes saber antes de escribir la gestión de errores. Siguiendo la especificación GraphQL over HTTP, una solicitud que llega a nuestros resolvers devuelve HTTP 200 incluso cuando una operación ha fallado. El fallo se informa dentro del cuerpo de la respuesta, no mediante el código de estado. Por lo tanto, esta comprobación no funciona:Content-Type no admitido, tienen el cuerpo vacío, así que comprueba que la respuesta sea JSON antes de analizarla:
- Una solicitud mal formada devuelve un estado de error: HTTP 400 por JSON no válido o una
queryausente, 413 por un cuerpo de más de 64 KB, 405 por un método distinto dePOSTy 415 por unContent-Typeno admitido. - Una query que no es válida para el esquema devuelve HTTP 400 solo si tu solicitud envía
Accept: application/graphql-response+json. Esto incluye un error de sintaxis, un campo desconocido, un tipo de argumento incorrecto, un valor de enum no válido y una query que supera los límites de consulta. Si envíasAccept: application/json, o ningún encabezadoAccept, el mismo error devuelve HTTP 200. En ambos casos, el cuerpo tiene un arrayerrorsy ningúndata.
errors.
La estructura del error
Cada error del resolver incluye su estado de la API, similar a HTTP, enextensions:
message: una descripción legible. Eliminamos las API Keys y otras credenciales de los mensajes de error del resolver, pero un error sobre un valor que enviaste, como una variable del tipo incorrecto, puede repetir ese valor. Tratamessagecomo posiblemente sensible antes de registrarlo.path: qué campo de tu query falló. Con varios campos en una solicitud, así es como sabes cuál.extensions.status: el estado HTTP que habría devuelto la llamada REST equivalente. Básate en este valor.extensions.code: el código de error numérico de Ayrshare, cuando el endpoint subyacente proporciona uno.extensions.retryAfter: presente en los 429 de cuota o rate limit del servicio subyacente cuando hay un tiempo de espera de reintento disponible. No está presente en el 429 del presupuesto de despacho por solicitud.
extensions.code con la referencia de códigos de error, o pásalo a explainError.
Éxito parcial
Si una solicitud pide varias cosas y solo algunas tienen éxito, obtienes tantodata como errors:
history tuvo éxito y sus datos se pueden usar. Solo hay que reintentar analytics. No descartes toda la respuesta porque haya errors: estarías tirando datos que ya se te han facturado.
Éxito parcial en publicaciones en varias redes
Una publicación en varias redes puede tener éxito en algunas y fallar en otras. Esto no se informa como un error de GraphQL, porque la operación en sí funcionó: hizo exactamente lo que pediste y te está indicando lo que ocurrió. El resultado separa los tres desenlaces:postIds: las redes en las que se publicó, con las URLs de sus publicaciones. Solo los éxitos.errors: las redes que fallaron, con el motivo.blocked: las redes que se detuvieron antes de intentarlo, por ejemplo por el circuit breaker por red tras fallos deterministas repetidos. Son distintas de los intentos ante el proveedor que devolvieron errores.
status es "error" si cualquier red falló, así que no es una señal fiable de que no se publicó nada. Lee postIds para saber qué se publicó.
Reintentos
La API GraphQL nunca reintenta automáticamente. Si una solicitud falla, no se ha vuelto a intentar nada en silencio en tu nombre. Esto importa sobre todo en las mutations.createPost expone idempotencyKey: genera una clave única antes del primer intento y luego reutiliza la misma clave y una carga útil idéntica en cada reintento. Un reintento ya resuelto reproduce el resultado original en lugar de repetir la escritura. No cambies a una clave nueva tras una respuesta ambigua.
boostFacebookPost e instagramBoostPost también reciben un idempotencyKey, y este protege dinero real. Un reintento con la misma clave y los mismos argumentos devuelve el resultado original, marcado con idempotentReplayed: true, en lugar de crear y pagar un segundo anuncio. Una clave cubre toda tu cuenta en ambas plataformas de Meta, así que nunca reutilices la clave de una promoción de Facebook para una promoción de Instagram.
Cuando se rechaza una clave, extensions.status te indica el motivo. createPost devuelve 409 mientras el primer intento aún se está procesando, así que espera y reintenta con la misma clave, y 400 cuando la carga útil difiere de la del primer intento. Las mutations de promoción devuelven 409 en ambos casos, y también cuando la clave se usó para una promoción en la otra plataforma.
Otras escrituras, como addComment, no tienen clave de idempotencia. Si se pierde su respuesta, comprueba el estado de la red social o de la API antes de decidir si es seguro volver a intentarlo.
Dos límites distintos informan ambos de un 429, y requieren una gestión diferente. El presupuesto de despacho solo rechaza campos raíz una vez que ya se han iniciado cinco llamadas a la API en la misma solicitud, y su mensaje empieza por Query exceeds the per-request dispatch budget: divide esos campos en solicitudes de cinco como máximo, sin necesidad de esperar. Cualquier otro 429 es un rate limit o una cuota: espera extensions.retryAfter segundos cuando esté presente; de lo contrario, aplica un backoff antes de reintentar, y reintenta solo los campos que fallaron. Ante un 5xx en una lectura, reintentar es seguro, con una excepción: generatePost es una query, pero un reintento vuelve a llamar al generador de IA, cuenta como otra llamada a la API y devuelve un texto distinto. Ante un 5xx en una escritura sin idempotencia, verifica si surtió efecto antes de reintentar.
Estados habituales
Los errores que genera el propio GraphQL antes de la ejecución, como un campo desconocido, un tipo de argumento incorrecto o un valor de enum no válido, no tienen
extensions.status. Devuelven HTTP 400 o 200 según tu encabezado Accept, como se describe arriba. Significan que la propia query es incorrecta, y no se realizó ni se facturó ninguna llamada a la API.