Error Handling

GraphQL errors are returned in the errors array of the response. The HTTP status code is always 200 — check the response body for errors.

Error Response Format

{
  "errors": [
    {
      "message": "Unauthenticated.",
      "extensions": {
        "category": "authentication"
      },
      "locations": [{ "line": 2, "column": 3 }],
      "path": ["me"]
    }
  ],
  "data": null
}

Error Categories

FieldTypeDescription
authentication401Invalid or missing API key / token — check credentials
authorization403Insufficient permissions — check user role and abilities
validation422Invalid input — check extensions.validation for field details
internal500Server error — retry with exponential backoff

Validation Errors

Validation errors include field-level details:

{
  "errors": [{
    "message": "Validation failed for the field [createPeople].",
    "extensions": {
      "category": "validation",
      "validation": {
        "input.email": ["The email field is required."],
        "input.firstname": ["The firstname field is required."]
      }
    }
  }]
}

Best Practices

  • Always check for the errors array in the response body
  • For authentication errors, refresh your token with refreshToken
  • For validation errors, check extensions.validation for field-level details
  • Implement exponential backoff for internal errors (start at 1s, max 30s)
  • Log the full error object including path for debugging

Handling in Code

// With @kanvas/core SDK
try {
  const lead = await kanvas.leads.createLead(input);
} catch (err) {
  if (err.graphQLErrors) {
    for (const error of err.graphQLErrors) {
      console.error(error.message);
      console.error(error.extensions?.category);
      console.error(error.extensions?.validation);
    }
  }
  if (err.networkError) {
    console.error("Network error:", err.networkError.message);
  }
}

// With raw fetch
const json = await res.json();
if (json.errors) {
  json.errors.forEach(e => console.error(e.message));
} else {
  // Use json.data
}