Помилки резолверів надходять з HTTP 200
Це найважливіше, що потрібно знати, перш ніж писати обробку помилок. Відповідно до специфікації GraphQL over HTTP, запит, який дійшов до наших резолверів, повертає HTTP 200, навіть якщо операція завершилася помилкою. Про збій повідомляється в тілі відповіді, а не кодом статусу. Тож така перевірка не працює:Content-Type, мають порожнє тіло, тому перед парсингом перевірте, що відповідь є JSON:
- Некоректний запит повертає статус помилки: HTTP 400 для невалідного JSON або відсутнього
query, 413 для тіла понад 64 KB, 405 для методу, відмінного відPOST, і 415 для непідтримуваногоContent-Type. - Запит, невалідний щодо схеми, повертає HTTP 400, лише якщо ваш запит надсилає
Accept: application/graphql-response+json. Це стосується синтаксичної помилки, невідомого поля, неправильного типу аргументу, некоректного значення enum і запиту, що перевищує ліміти запитів. Якщо ви надсилаєтеAccept: application/jsonабо не надсилаєте заголовокAccept, та сама помилка повертає HTTP 200. У будь-якому разі тіло містить масивerrorsі не міститьdata.
errors.
Структура помилки
Кожна помилка резолвера містить свій HTTP-подібний статус API вextensions:
message— зрозумілий людині опис. Ми видаляємо API Key та інші облікові дані з повідомлень про помилки резолверів, але помилка щодо надісланого вами значення, наприклад змінної неправильного типу, може повторювати це значення. Перш ніж записуватиmessageу логи, вважайте його потенційно чутливим.path— яке поле у вашому запиті завершилося помилкою. Коли в одному запиті кілька полів, саме так ви дізнаєтеся, яке саме.extensions.status— HTTP-статус, який повернув би відповідний REST-виклик. Орієнтуйтеся саме на нього.extensions.code— числовий код помилки Ayrshare, якщо базовий ендпоінт його надає.extensions.retryAfter— присутній в upstream-відповідях 429 щодо квоти або rate limit, коли доступна затримка перед повторною спробою. Він відсутній у відповіді 429 щодо бюджету викликів на запит.
extensions.code разом із довідником кодів помилок або передайте його в explainError.
Частковий успіх
Якщо запит запитує кілька речей і лише деякі з них успішні, ви отримуєте іdata, і errors:
history виконано успішно, і його дані можна використовувати. Повторити потрібно лише analytics. Не відкидайте всю відповідь через наявність errors, бо так ви викинете дані, за які вже заплатили.
Частковий успіх для дописів у кілька соцмереж
Допис у кілька соцмереж може бути успішним в одних і завершитися помилкою в інших. Про це не повідомляється як про помилку GraphQL, тому що сама операція спрацювала: вона зробила саме те, що ви просили, і повідомляє, що сталося. Результат розділяє три можливі наслідки:postIds— соцмережі, у яких допис опубліковано, з URL дописів. Лише успішні.errors— соцмережі, де сталася помилка, із причиною.blocked— соцмережі, для яких публікацію зупинено до спроби, наприклад запобіжником (circuit breaker) для окремої соцмережі після повторюваних детермінованих збоїв. Вони відокремлені від спроб, у яких провайдер повернув помилки.
status має значення "error", якщо будь-яка соцмережа завершилася помилкою, тому це не надійний сигнал того, що нічого не опубліковано. Щоб дізнатися, що саме опубліковано, читайте postIds.
Повторні спроби
GraphQL API ніколи не повторює запити автоматично. Якщо запит завершився помилкою, від вашого імені нічого не було непомітно спробувано ще раз. Найбільше це важливо для mutations.createPost надає idempotencyKey: згенеруйте унікальний ключ перед першою спробою, а потім використовуйте той самий ключ і ідентичне корисне навантаження для кожної повторної спроби. Завершена повторна спроба відтворює початковий результат замість повторного запису. Не переходьте на новий ключ після неоднозначної відповіді.
boostFacebookPost і instagramBoostPost також приймають idempotencyKey, і він захищає реальні гроші. Повторна спроба з тим самим ключем і тими самими аргументами повертає початковий результат із позначкою idempotentReplayed: true замість того, щоб створити другу рекламу й заплатити за неї. Один ключ діє для всього вашого акаунта на обох платформах Meta, тому ніколи не використовуйте ключ просування у Facebook повторно для просування в Instagram.
Коли ключ відхилено, extensions.status повідомляє причину. createPost повертає 409, поки перша спроба ще обробляється, тож зачекайте й повторіть із тим самим ключем, і 400, коли корисне навантаження відрізняється від першої спроби. Mutations просування повертають 409 в обох випадках, а також коли ключ уже використовувався для просування на іншій платформі.
Інші операції запису, як-от addComment, не мають ключа ідемпотентності. Якщо їхню відповідь втрачено, перевірте стан у соцмережі або в API, перш ніж вирішувати, чи безпечна ще одна спроба.
Два різні ліміти повертають 429, і їх потрібно обробляти по-різному. Бюджет викликів відхиляє кореневі поля лише тоді, коли в тому самому запиті вже запущено п’ять викликів API, а його повідомлення починається з Query exceeds the per-request dispatch budget: розділіть ці поля на запити щонайбільше з п’ятьма полями, чекати не потрібно. Будь-яка інша відповідь 429 означає rate limit або квоту: зачекайте extensions.retryAfter секунд, якщо це поле присутнє, інакше збільшуйте затримку перед повторною спробою, і повторюйте лише поля, які завершилися помилкою. Для 5xx під час читання повторна спроба безпечна з одним винятком: generatePost — це query, але повторна спроба знову викликає AI-генератор, рахується як ще один виклик API і повертає інший текст. Для 5xx під час запису без ідемпотентності перед повторною спробою з’ясуйте, чи набула операція чинності.
Поширені статуси
Помилки, які генерує сам GraphQL до виконання, як-от невідоме поле, неправильний тип аргументу або некоректне значення enum, не мають
extensions.status. Вони повертають HTTP 400 або 200 залежно від вашого заголовка Accept, як описано вище. Вони означають, що неправильний сам запит, і жоден виклик API не було здійснено чи тарифіковано.