Fouten
Er zijn twee soorten fouten, en ze vragen om verschillende dingen van je code. Iets mis met het verzoek zelf is een programmeerfout of een storing. Iets mis met wat je vroeg is iets dat je aan een gebruiker kunt laten zien.
Fouten in het verzoek
Deze staan in errors op de wortel, met een code in extensions. Er is
dan geen data, want er is niets uitgevoerd.
- Name
GRAPHQL_PARSE_FAILED- Type
- 200
- Description
De query is niet te lezen. Een haakje vergeten.
- Name
GRAPHQL_VALIDATION_FAILED- Type
- 200
- Description
De query klopt niet tegen het schema: een veld dat niet bestaat, een argument dat ontbreekt, een verkeerd type.
- Name
MAX_COST_EXCEEDED- Type
- 200
- Description
firstoflastligt buiten 1–250.
- Name
THROTTLED- Type
- 200
- Description
De query past niet in je punten. Zie Kosten en limieten.
- Name
INTERNAL_SERVER_ERROR- Type
- 500
- Description
Het ging bij ons mis. Probeer het opnieuw; blijft het gebeuren, mail ons het
X-Request-Iduit het antwoord.
Veld bestaat niet
{
"errors": [
{
"message": "Cannot query field \"kleur\" on type \"Theme\".",
"extensions": { "code": "GRAPHQL_VALIDATION_FAILED" }
}
]
}
Te duur
{
"errors": [
{
"message": "Throttled: deze query kost 1002 punten en er zijn er 1000 beschikbaar.",
"extensions": { "code": "THROTTLED" }
}
],
"extensions": {
"cost": {
"requestedQueryCost": 1002,
"actualQueryCost": null,
"throttleStatus": {
"maximumAvailable": 1000,
"currentlyAvailable": 1000,
"restoreRate": 50
}
}
}
}
Op HTTP-niveau
Een paar dingen worden afgewezen voordat er een GraphQL-antwoord bestaat. Die geven een andere statuscode en één melding als tekst.
- Name
400- Type
- Bad Request
- Description
De body is geen geldige JSON, of er zit geen
queryin.
- Name
401- Type
- Unauthorized
- Description
Sleutel ontbreekt, is onbekend of is ingetrokken. Zie Authenticatie.
- Name
404- Type
- Not Found
- Description
Onbekende API-versie, of een pad dat niet bestaat.
- Name
405- Type
- Method Not Allowed
- Description
Iets anders dan
POST. DeAllow-header noemt wat wel kan.
- Name
406- Type
- Not Acceptable
- Description
Je
Accept-header sluit JSON uit. Laat hem weg of sta JSON toe.
Fouten in wat je vroeg
Een dossiernummer dat al bestaat, een datum die niet klopt, een thema dat je
na het bestellen nog wilt wijzigen: dat zijn geen programmeerfouten maar
uitkomsten. Ze staan in userErrors in de payload van de mutatie, en de
HTTP-status is gewoon 200.
Elke melding wijst het pad naar het veld aan, zodat je hem in je eigen formulier op de goede plek kunt tonen.
- Name
field- Type
- [String!]
- Description
Het pad van buiten naar binnen, bijvoorbeeld
["input", "familyContact", "email"].
- Name
message- Type
- String!
- Description
Wat er mis is, in het Nederlands.
- Name
code- Type
- enum
- Description
BLANK,INVALID,TAKEN,NOT_FOUND,IMMUTABLEofUNPROCESSABLE.
Dossiernummer al gebruikt
{
"data": {
"cardCreate": {
"card": null,
"userErrors": [
{
"field": ["input", "externalDossierId"],
"message": "is al gebruikt voor een andere kaart",
"code": "TAKEN"
}
]
}
}
}
Twee velden tegelijk
{
"data": {
"cardCreate": {
"card": null,
"userErrors": [
{
"field": ["input", "deceased", "dateOfBirth"],
"message": "moet een datum zijn als JJJJ-MM-DD",
"code": "INVALID"
},
{
"field": ["input", "familyContact", "email"],
"message": "moet een geldig e-mailadres zijn",
"code": "INVALID"
}
]
}
}
}
Vraag userErrors altijd op. Laat je ze uit je query weg, dan lijkt een
mislukte mutatie op een geslaagde met een lege payload, en dan ontdek je pas
dagen later dat er kaarten ontbreken.
Wat de codes betekenen
- Name
BLANK- Type
- verplicht veld ontbreekt
- Description
Vul het aan en probeer opnieuw.
- Name
INVALID- Type
- waarde klopt niet
- Description
Een datum in het verkeerde formaat, een adres dat geen adres is, een id dat nergens naar wijst.
- Name
TAKEN- Type
- al in gebruik
- Description
Vrijwel altijd een dossiernummer dat al een kaart heeft. Vaak betekent dit dat je verzoek de vorige keer wél is aangekomen; zie idempotency.
- Name
NOT_FOUND- Type
- bestaat niet, of niet voor jou
- Description
Een kaart van een andere partner bestaat voor jou niet.
- Name
IMMUTABLE- Type
- kan nu niet meer
- Description
Het thema na het bestellen, bijvoorbeeld. De bestelling hangt aan dat product.
- Name
UNPROCESSABLE- Type
- klopt, maar lukte niet
- Description
Het verzoek is in orde maar kon niet worden uitgevoerd, bijvoorbeeld een portretfoto op een adres dat niet reageert.
Hoe je hierop programmeert
Drie takken, en je bent er:
errorsop de wortel: jouw bug of onze storing. Loggen, melden, niet opnieuw proberen (behalve bijTHROTTLEDenINTERNAL_SERVER_ERROR).userErrorsgevuld: laat zien aan degene die het formulier invult.- Allebei leeg: gelukt.
Eén plek waar alles langskomt
export async function rouwkaart(query, variables) {
const antwoord = await fetch(ENDPOINT, {
method: 'POST',
headers: {
'X-Rouwkaart-Access-Token': process.env.ROUWKAART_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({query, variables}),
})
if (antwoord.status === 401) {
throw new Error('Sleutel klopt niet of is ingetrokken')
}
const {data, errors, extensions} = await antwoord.json()
if (errors?.length) {
const code = errors[0].extensions?.code
// Even wachten en opnieuw; de rest is onze of jouw fout.
if (code === 'THROTTLED') {
const seconden = Number(antwoord.headers.get('Retry-After') ?? 1)
await new Promise((r) => setTimeout(r, seconden * 1000))
return rouwkaart(query, variables)
}
throw new Error(`${code}: ${errors[0].message}`)
}
return {data, cost: extensions?.cost}
}
Elk antwoord draagt een kenmerk
In de header X-Request-Id staat een uniek id per verzoek. Stuur dat mee als je ons iets vraagt over een verzoek dat misging; dan kunnen wij precies dat verzoek terugvinden in onze logs.