Error Handling
Overview
The GraphQL API returns errors in a standard format. Understanding error responses helps you build robust integrations.
Error Response Structure
GraphQL errors appear in the errors array of the response:
{
"errors": [
{
"message": "Error description",
"locations": [{ "line": 2, "column": 3 }],
"path": ["fieldName"],
"extensions": {
"code": "ERROR_CODE",
"additionalInfo": "..."
}
}
],
"data": null
}Common Error Types
Syntax Errors
Invalid GraphQL syntax:
{
"errors": [{
"message": "Syntax Error: Expected Name, found }",
"locations": [{ "line": 3, "column": 5 }]
}]
}Field Errors
Querying fields that don't exist:
{
"errors": [{
"message": "Cannot query field \"invalidField\" on type \"Product\"",
"locations": [{ "line": 4, "column": 7 }]
}]
}Authentication Errors
Missing or invalid credentials:
{
"errors": [{
"message": "Authentication required",
"extensions": { "code": "UNAUTHENTICATED" }
}]
}Permission Errors
Insufficient permissions for requested data:
{
"errors": [{
"message": "Insufficient permissions to access this resource",
"extensions": { "code": "FORBIDDEN" }
}]
}Validation Errors
Invalid argument values:
{
"errors": [{
"message": "Invalid value for argument 'first': must be positive integer",
"path": ["productViewConnection"]
}]
}Partial Success
GraphQL can return partial results with errors:
{
"data": {
"orderViewConnection": {
"edges": [...]
}
},
"errors": [{
"message": "Could not resolve field 'customer'",
"path": ["orderViewConnection", "edges", 0, "node", "customer"]
}]
}In this case:
datacontains successful parts of the queryerrorsdescribes what failed- Check both fields in your client code
Best Practices
1. Always Check for Errors
const response = await fetch('/graphql', { ... })
const json = await response.json()
if (json.errors) {
console.error('GraphQL errors:', json.errors)
// Handle errors appropriately
}
if (json.data) {
// Process successful data
}2. Handle HTTP Status Codes
200 OK- Request processed (but may contain GraphQL errors)400 Bad Request- Invalid GraphQL request401 Unauthorized- Authentication failed500 Internal Server Error- Server error
3. Implement Retry Logic
For transient errors:
async function queryWithRetry(query, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await executeQuery(query)
if (!response.errors || !isTransientError(response.errors)) {
return response
}
} catch (error) {
if (i === maxRetries - 1) throw error
}
await sleep(Math.pow(2, i) * 1000) // Exponential backoff
}
}4. Log Error Details
Include in logs:
- Error messages
- Query that caused the error
- Variables used
- User/session context
- Timestamp
5. Graceful Degradation
Design UI to handle:
- Missing optional fields
- Partial data availability
- Permission-restricted fields
Testing Error Scenarios
Test your error handling with:
# Test invalid field
query {
productViewConnection(first: 10) {
edges {
node {
invalidFieldName
}
}
}
}
# Test invalid argument
query {
productViewConnection(first: -10) {
edges {
node {
productId
}
}
}
}