Błędy API mają ten sam kształt, niezależnie od operacji. Twój kod rozpoznaje błąd po stałych kodach w extensions, nigdy po treści komunikatu.
Koperta błędu
Błędy przychodzą w tablicy errors odpowiedzi GraphQL. Każdy element ma wextensions:
code: kategoria błędu, zawsze obecna (tabela niżej);subCode: doprecyzowanie kategorii, gdy jest potrzebne;params: wartości, które pomagają obsłużyć błąd, np. brakujący zakres albo limit;fieldErrors: błędy poszczególnych pól wejściowych (przyVALIDATION);message: angielski opis dla programisty, do logów, bez gwarancji stałej treści;requestId: identyfikator żądania, ten sam co w nagłówkuX-Request-IDodpowiedzi.
{ "errors": [ { "message": "Query nests 8 levels of fields; at most 6 are allowed", "extensions": { "code": "BAD_REQUEST", "subCode": "API_QUERY_TOO_DEEP", "params": { "depth": 8, "maxDepth": 6 }, "message": "Query nests 8 levels of fields; at most 6 are allowed", "requestId": "7b0d6a52-3c41-4f0e-9a8e-2f6d1c9e4b17" } } ]}Błąd walidacji wskazuje każde błędne pole wejściowe jego ścieżką w fieldErrors[].path:
{ "code": "VALIDATION", "message": "Validation failed", "fieldErrors": [ { "path": "email", "code": "INVALID_EMAIL", "message": "Invalid email" } ], "requestId": "1c9e4b17-7b0d-4a52-8e2f-6d3c414f0e9a"}Odpowiedzi 503 z sub-kodem API_KEY_CHECK_UNAVAILABLE alboAPI_IDEMPOTENCY_UNAVAILABLE mają tę samą kopertę. Inna odpowiedź ze statusem HTTP 5xx może nie mieć tablicy errors, np. gdy Prynt jest chwilowo niedostępny: dostaniesz wtedy stronę błędu HTML albo zwykły tekst. Traktuj każdą odpowiedź 5xx jak błąd przejściowy.
Jak obsługiwać błędy
- Sprawdzaj tablicę
errorsw każdej odpowiedzi, także ze statusem HTTP 200. Sukces to tylko odpowiedź 2xx bezerrorsi z obiektemdata. - Odmowa przed wykonaniem ma swój status HTTP i nie ma
data: 401 (zły lub wygasły klucz), 403 (brak akceptacji, wstrzymanie, operacja spoza API, brak zakresu, przeglądarka), 400 (zapytanie spoza schematu, limity zapytania, złyIdempotency-Key), 409 (konfliktIdempotency-Key), 429 (limit żądań), 500 (INTERNAL: publiczne API chwilowo niedostępne) i 503 (chwilowa niedostępność). Błędy, które zapadają w trakcie wykonywania operacji, przychodzą ze statusem HTTP 200: walidacja, brak obiektu, reguły danych i błędy wewnętrzne. GraphQL zwraca wtedy obok błędówdataz wynikami pól, które się udały, a pole, którego dotyczy błąd, wskazujepath. - Rozstrzygaj po
code, a potem posubCode, nie po statusie HTTP. NieznanysubCodeobsłuż według jego kategorii: nowe sub-kody mogą dochodzić w kolejnych wydaniach. - Ponawiaj tylko błędy przejściowe:
RATE_LIMITED,INTERNAL(także 503API_KEY_CHECK_UNAVAILABLEiAPI_IDEMPOTENCY_UNAVAILABLE),API_IDEMPOTENCY_IN_PROGRESS, odpowiedzi 5xx i błędy sieci. Mutacje ponawiaj z tym samymIdempotency-Key. Gotowy wzorzec: Obsługa błędów i ponowień. - Zapisuj
requestIdw logach. Gdy prosisz nas o pomoc, podaj go: po nim znajdziemy żądanie.
Kategorie
code | Znaczenie | Co zrobić |
|---|---|---|
VALIDATION | Dane wejściowe nie przeszły walidacji albo operacja narusza regułę danych (np. klient zablokowany, niedozwolona zmiana statusu). Błędy konkretnych pól są w fieldErrors, pozostałe opisuje message. | Popraw dane według fieldErrors albo message. Nie ponawiaj żądania bez zmian. |
UNAUTHENTICATED | Klucz nie został rozpoznany: jest błędny, unieważniony albo wygasł. | Sprawdź nagłówek Authorization i ważność klucza. Nie ponawiaj z tym samym kluczem. |
FORBIDDEN | Klucz jest poprawny, ale integracja nie może wykonać tej operacji, albo API odrzuciło żądanie, zanim sprawdziło klucz (połączenie przez http://, strona spoza Prynt). | Sprawdź subCode: brakujący zakres, operacja spoza publicznego API, brak akceptacji, wstrzymanie, wywołanie z przeglądarki, połączenie bez szyfrowania albo strona spoza Prynt. |
NOT_FOUND | Obiekt, którego dotyczy żądanie, nie istnieje. | Sprawdź identyfikator. Nie ponawiaj. |
CONFLICT | Żądanie koliduje z bieżącym stanem danych albo z wcześniejszym żądaniem o tym samym Idempotency-Key. | Sprawdź subCode. Ponów tylko przy API_IDEMPOTENCY_IN_PROGRESS. |
RATE_LIMITED | Integracja przekroczyła limit żądań na minutę. | Odczekaj liczbę sekund z nagłówka Retry-After (params.retryAfterSeconds) i ponów. |
BAD_REQUEST | Żądania nie da się wykonać: zapytanie spoza publicznego schematu, przekroczony limit zapytania albo naruszona reguła biznesowa. | Popraw żądanie według subCode i message. Nie ponawiaj bez zmian. |
INTERNAL | Błąd po stronie Prynt: nieoczekiwany albo chwilowa niedostępność (sub-kod API_KEY_CHECK_UNAVAILABLE lub API_IDEMPOTENCY_UNAVAILABLE, HTTP 503). Odpowiedź nie zawiera szczegółów. | Ponów z rosnącym odstępem (mutację tylko z tym samym Idempotency-Key). Gdy błąd się powtarza, napisz do nas i podaj requestId. |
Sub-kody dostępu do API
Klucz, integracja, zakresy, limity zapytania i Idempotency-Key. Każda z tych odmów zapada, zanim operacja się wykona, więc przychodzi z własnym statusem HTTP (podanym przy sub-kodzie) i bez data. Odmowy klucza zapadają, zanim API w ogóle przeczyta dokument: dostaje je nawet { __typename } albo zapytanie z błędem składni.
subCode | Znaczenie | Co zrobić |
|---|---|---|
API_TOKEN_INVALID | Klucz ma zły format, nie istnieje albo został unieważniony. API celowo nie rozróżnia tych przypadków. | Sprawdź, czy wysyłasz cały klucz po słowie Bearer. Jeśli tak, poproś administratora drukarni o nowy klucz. |
API_TOKEN_EXPIRED | Klucz minął datę ważności. | Poproś administratora drukarni o nowy klucz. Następnym razem zacznij rotację przed datą ważności. |
API_INTEGRATION_NOT_APPROVED | Integracja nie ma akceptacji Prynt: wniosek czeka na decyzję, został odrzucony albo akceptacja wygasła. | Skontaktuj się z administratorem drukarni. |
API_INTEGRATION_SUSPENDED | Integracja jest wstrzymana. Klucze zaczną działać po wznowieniu. | Skontaktuj się z administratorem drukarni. Nie ponawiaj w pętli. |
API_OPERATION_NOT_AVAILABLE | Operacja nie należy do publicznego API. | Sprawdź listę operacji w referencji API. |
API_SCOPE_MISSING | Integracja nie ma zakresu, którego wymaga operacja, pole albo filtr. params.scope podaje brakujący zakres, a params.coordinate element, gdy zakresu wymaga pole, argument albo filtr (a nie sama operacja). | Administrator drukarni może poprosić o rozszerzenie zakresów. Do tego czasu usuń element z zapytania. |
API_TOKEN_BROWSER_USE | Operację z kluczem wysłała przeglądarka (żądanie ma nagłówek Origin). | Wywołuj API wyłącznie z serwera. Klucz, który trafił do kodu strony, traktuj jak ujawniony. |
API_TOKEN_INSECURE_TRANSPORT | Klucz przyszedł zwykłym http://, bez szyfrowania. API odrzuca takie żądanie, zanim sprawdzi klucz, ale klucz przeszedł już przez sieć jawnym tekstem. | Zmień adres API na https://. Klucz traktuj jak ujawniony: poproś administratora drukarni o jego unieważnienie i wdróż nowy. |
ORIGIN_NOT_ALLOWED | Żądanie ma nagłówek Origin strony spoza Prynt. API odrzuca je przed sprawdzeniem klucza, z kluczem i bez. | Wywołuj API z serwera, bez nagłówka Origin. Klucz, który trafił do kodu strony, traktuj jak ujawniony. |
API_QUERY_INVALID | Dokument nie pasuje do publicznego schematu: nieznane pole, argument lub typ, błąd składni albo introspekcja. | Sprawdź zapytanie względem pobranego schematu (SDL). Nie ponawiaj bez zmian. |
API_QUERY_TOO_DEEP | Zapytanie zagnieżdża pola głębiej, niż pozwala limit. | Spłaszcz zapytanie. Powiązane dane pobierz osobnym zapytaniem. |
API_QUERY_TOO_COMPLEX | Szacowany koszt zapytania przekracza limit albo dokument rozwija się do zbyt wielu pól. | Zmniejsz rozmiar strony albo liczbę pobieranych powiązań. |
API_PAGE_SIZE_EXCEEDED | Rozmiar strony jest poza dozwolonym zakresem. | Poproś o stronę w dozwolonym zakresie i przejdź po kolejnych stronach. |
API_IDEMPOTENCY_KEY_INVALID | Nagłówek Idempotency-Key jest pusty, za długi albo ma znaki spoza drukowalnego ASCII. | Użyj od 1 do 255 drukowalnych znaków ASCII, najlepiej UUID. |
API_IDEMPOTENCY_KEY_REUSED | Ten Idempotency-Key był już użyty z inną treścią żądania. | Każda nowa operacja potrzebuje nowego klucza. Nie zmieniaj treści przy ponowieniu. |
API_IDEMPOTENCY_IN_PROGRESS | Żądanie z tym Idempotency-Key jeszcze trwa. | Ponów za chwilę z tym samym kluczem i tą samą treścią. |
API_IDEMPOTENCY_RESPONSE_TOO_LARGE | Mutacja z tym Idempotency-Key już się wykonała, ale jej odpowiedź miała około 64 KiB lub więcej i nie została zachowana do powtórki. | Nie wysyłaj mutacji ponownie. Pobierz jej wynik zapytaniem. |
API_IDEMPOTENCY_UNAVAILABLE | Mutacja ma nagłówek Idempotency-Key, ale Prynt nie może teraz zapamiętać klucza. Żeby ponowienie nie wykonało zapisu drugi raz, API odrzuciło mutację przed wykonaniem: nic się nie zapisało. | Ponów z rosnącym odstępem, z tym samym Idempotency-Key i tą samą treścią. |
API_KEY_CHECK_UNAVAILABLE | Prynt nie może teraz sprawdzić klucza. Błąd nie mówi nic o kluczu: może być poprawny. | Ponów z rosnącym odstępem. Nie wymieniaj klucza. Gdy błąd się powtarza, napisz do nas i podaj requestId. |
Sub-kody zapisu danych
Reguły danych, które może naruszyć każda mutacja. Przychodzą ze statusem HTTP 200.
subCode | Znaczenie | Co zrobić |
|---|---|---|
UNIQUE_VIOLATION | Obiekt z taką unikalną wartością już istnieje. | Nie twórz duplikatu: odczytaj istniejący obiekt albo zmień wartość. |
FOREIGN_KEY_VIOLATION | Wskazany powiązany obiekt nie istnieje. | Sprawdź identyfikatory powiązanych obiektów. |
VALUE_TOO_LONG | Wartość jest dłuższa, niż pozwala pole. | Skróć wartość; pole wskazuje fieldErrors, gdy da się je ustalić. |
REQUIRED_VALUE_MISSING | Brakuje wymaganej wartości. | Uzupełnij wartość; pole wskazuje fieldErrors, gdy da się je ustalić. |
RECORD_NOT_FOUND | Obiekt, którego dotyczy zapis, nie istnieje. | Sprawdź identyfikator. Nie ponawiaj. |
Błędy pól
Wartości fieldErrors[].code. Szczegóły, np. dozwoloną długość, podajefieldErrors[].params.
code | Znaczenie |
|---|---|
REQUIRED | Pole jest wymagane. |
INVALID_TYPE | Wartość ma zły typ. |
TOO_SHORT | Tekst lub lista jest za krótka. |
TOO_LONG | Tekst lub lista jest za długa. |
TOO_SMALL | Liczba lub data jest za mała. |
TOO_BIG | Liczba lub data jest za duża. |
INVALID_EMAIL | To nie jest poprawny adres e-mail. |
INVALID_UUID | To nie jest poprawny identyfikator UUID. |
INVALID_ENUM | Wartość spoza dozwolonej listy. |
INVALID_FORMAT | Wartość ma zły format. |
NOT_UNIQUE | Taka wartość już istnieje. |
INVALID | Wartość jest nieprawidłowa (bez bliższego rodzaju). |