Skip to main content

Error Handling

The Lumar GraphQL API follows the standard GraphQL error response conventions. Understanding how errors are structured will help you build resilient integrations.

GraphQL error response structure

When a query fails, the response includes an errors array alongside (or instead of) the data field. Each error object contains a message string and an optional extensions object with a machine-readable code.

query GetProject($id: ObjectID!) {
getProject(id: $id) {
id
name
}
}

Try in explorer

Key points:

  • Partial data is possible -- some fields may resolve successfully while others produce errors.
  • The extensions.code field provides a stable identifier you can use for programmatic error handling.

HTTP status codes

StatusMeaning
200Request completed. Check the errors array for partial failures.
400Malformed query or invalid variables.
401Missing or invalid authentication token.
403Authenticated but insufficient permissions for the requested resource.
429Rate limit exceeded. See Rate Limits.
500Unexpected server error. Retry with exponential backoff.

Authentication errors

An invalid or expired token produces a 401 response with an UNAUTHENTICATED error code.

query GetMyAccounts {
me {
accounts(first: 5) {
nodes {
id
name
}
}
}
}

Try in explorer

Common authentication issues:

  • Expired session token -- tokens from createSessionUsingUserKey expire after a period of inactivity. Re-authenticate to obtain a new token.
  • Revoked API key -- if a user key has been revoked, authentication will fail. Generate a new key.
  • Wrong header -- ensure the token is sent in the x-auth-token header (not Authorization: Bearer).

Rate limiting

When you exceed the rate limit you will receive an HTTP 429 response. Implement exponential backoff to handle this gracefully:

async function fetchWithRetry(url: string, options: RequestInit, maxRetries = 5): Promise<Response> {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, options);

if (response.status === 429) {
const delay = Math.min(1000 * Math.pow(2, attempt), 30000);
console.warn(`Rate limited. Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}

return response;
}

throw new Error("Max retries exceeded");
}

Troubleshooting common errors

ErrorCauseSolution
UNAUTHENTICATEDMissing or invalid tokenRe-authenticate with createSessionUsingUserKey
FORBIDDENAccount lacks required feature or permissionContact your account administrator
BAD_USER_INPUTInvalid variable values or missing required fieldsCheck variable types against the schema
INTERNAL_SERVER_ERRORUnexpected server issueRetry after a brief delay; contact support if persistent