Przejdź do głównej zawartości

Błędy API

Dla: Programista

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 (przy VALIDATION);
  • message: angielski opis dla programisty, do logów, bez gwarancji stałej treści;
  • requestId: identyfikator żądania, ten sam co w nagłówku X-Request-ID odpowiedzi.
Przykład: za głębokie zapytanie
{
"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:

extensions błędu walidacji
{
"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

  1. Sprawdzaj tablicę errors w każdej odpowiedzi, także ze statusem HTTP 200. Sukces to tylko odpowiedź 2xx bez errors i z obiektem data.
  2. 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ły Idempotency-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ów data z wynikami pól, które się udały, a pole, którego dotyczy błąd, wskazuje path.
  3. Rozstrzygaj po code, a potem po subCode, nie po statusie HTTP. NieznanysubCode obsłuż według jego kategorii: nowe sub-kody mogą dochodzić w kolejnych wydaniach.
  4. Ponawiaj tylko błędy przejściowe: RATE_LIMITED, INTERNAL (także 503API_KEY_CHECK_UNAVAILABLE i API_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ń.
  5. Zapisuj requestId w logach. Gdy prosisz nas o pomoc, podaj go: po nim znajdziemy żądanie.

Kategorie

codeZnaczenieCo zrobić
VALIDATIONDane 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.
UNAUTHENTICATEDKlucz nie został rozpoznany: jest błędny, unieważniony albo wygasł.Sprawdź nagłówek Authorization i ważność klucza. Nie ponawiaj z tym samym kluczem.
FORBIDDENKlucz 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_FOUNDObiekt, 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_LIMITEDIntegracja 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.
INTERNALBłą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.

subCodeZnaczenieCo zrobić
API_TOKEN_INVALID
UNAUTHENTICATED · HTTP 401
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
UNAUTHENTICATED · HTTP 401
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
FORBIDDEN · HTTP 403
Integracja nie ma akceptacji Prynt: wniosek czeka na decyzję, został odrzucony albo akceptacja wygasła.Skontaktuj się z administratorem drukarni.
API_INTEGRATION_SUSPENDED
FORBIDDEN · HTTP 403
Integracja jest wstrzymana. Klucze zaczną działać po wznowieniu.Skontaktuj się z administratorem drukarni. Nie ponawiaj w pętli.
API_OPERATION_NOT_AVAILABLE
FORBIDDEN · HTTP 403
Operacja nie należy do publicznego API.Sprawdź listę operacji w referencji API.
API_SCOPE_MISSING
FORBIDDEN · HTTP 403
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).
params: scope, coordinate
Administrator drukarni może poprosić o rozszerzenie zakresów. Do tego czasu usuń element z zapytania.
API_TOKEN_BROWSER_USE
FORBIDDEN · HTTP 403
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
FORBIDDEN · HTTP 403
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
FORBIDDEN · HTTP 403
Żą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
BAD_REQUEST · HTTP 400
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
BAD_REQUEST · HTTP 400
Zapytanie zagnieżdża pola głębiej, niż pozwala limit.
params: depth, maxDepth
Spłaszcz zapytanie. Powiązane dane pobierz osobnym zapytaniem.
API_QUERY_TOO_COMPLEX
BAD_REQUEST · HTTP 400
Szacowany koszt zapytania przekracza limit albo dokument rozwija się do zbyt wielu pól.
params: complexity, maxComplexity, maxFields
Zmniejsz rozmiar strony albo liczbę pobieranych powiązań.
API_PAGE_SIZE_EXCEEDED
BAD_REQUEST · HTTP 400
Rozmiar strony jest poza dozwolonym zakresem.
params: argument, requested, minPageSize, maxPageSize
Poproś o stronę w dozwolonym zakresie i przejdź po kolejnych stronach.
API_IDEMPOTENCY_KEY_INVALID
BAD_REQUEST · HTTP 400
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
CONFLICT · HTTP 409
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
CONFLICT · HTTP 409
Żą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
CONFLICT · HTTP 409
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.
params: maxBytes
Nie wysyłaj mutacji ponownie. Pobierz jej wynik zapytaniem.
API_IDEMPOTENCY_UNAVAILABLE
INTERNAL · HTTP 503
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
INTERNAL · HTTP 503
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.

subCodeZnaczenieCo zrobić
UNIQUE_VIOLATION
CONFLICT · HTTP 200
Obiekt z taką unikalną wartością już istnieje.Nie twórz duplikatu: odczytaj istniejący obiekt albo zmień wartość.
FOREIGN_KEY_VIOLATION
BAD_REQUEST · HTTP 200
Wskazany powiązany obiekt nie istnieje.Sprawdź identyfikatory powiązanych obiektów.
VALUE_TOO_LONG
BAD_REQUEST · HTTP 200
Wartość jest dłuższa, niż pozwala pole.Skróć wartość; pole wskazuje fieldErrors, gdy da się je ustalić.
REQUIRED_VALUE_MISSING
BAD_REQUEST · HTTP 200
Brakuje wymaganej wartości.Uzupełnij wartość; pole wskazuje fieldErrors, gdy da się je ustalić.
RECORD_NOT_FOUND
NOT_FOUND · HTTP 200
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.

codeZnaczenie
REQUIREDPole jest wymagane.
INVALID_TYPEWartość ma zły typ.
TOO_SHORTTekst lub lista jest za krótka.
TOO_LONGTekst lub lista jest za długa.
TOO_SMALLLiczba lub data jest za mała.
TOO_BIGLiczba lub data jest za duża.
INVALID_EMAILTo nie jest poprawny adres e-mail.
INVALID_UUIDTo nie jest poprawny identyfikator UUID.
INVALID_ENUMWartość spoza dozwolonej listy.
INVALID_FORMATWartość ma zły format.
NOT_UNIQUETaka wartość już istnieje.
INVALIDWartość jest nieprawidłowa (bez bliższego rodzaju).