Disclaimer: This website requires Please enable JavaScript in your browser settings for the best experience.

Dev guideRecipesAPI ReferenceChangelog
Dev guideRecipesUser GuidesNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev guide

Error handling and rate limits

Information on how GraphQL handles errors and various rate limits.

GraphQL error handling returns partial data and an errors field that explains issues, rather than failing the entire request. Rate limits protect servers by restricting query volume or complexity, ensuring fair use and maintaining performance.

Understand GraphQL error responses

GraphQL returns errors in a standardized format with detailed information about what went wrong. The following JSON response shows a typical GraphQL error format. The errors array contains detailed information about the error, including a message, the location in the query where the error occurred, the path to the problematic field, and any additional extensions or stack traces that provide more context.

{
  "errors": [
    {
      "message": "Cannot query field 'invalidField' on type 'ArticlePage'",
      "locations": [
        {
          "line": 4,
          "column": 7
        }
      ],
      "path": ["ArticlePage", "items", 0, "invalidField"],
      "extensions": {
        "code": "GRAPHQL_VALIDATION_FAILED",
        "exception": {
          "stacktrace": ["Error: Cannot query field..."]
        }
      }
    }
  ],
  "data": null
}

Error types and HTTP status codes

Syntax errors (HTTP 400)

Syntax errors happen when your GraphQL queries are malformed, such as missing brackets or incorrect syntax.

The following query is incomplete due to a missing closing bracket. These syntax errors prevent query execution and result in an error message indicating where the error occurred.

# Syntax error - missing closing bracket
query GetArticles {
  ArticlePage {
    items {
      Name
      RelativePath
    # Missing closing bracket

When this error happens, you receive a response like the following:

{
  "errors": [
    {
      "message": "Syntax Error: Expected Name, found EOF",
      "locations": [{"line": 7, "column": 1}]
    }
  ]
}

Validation errors (HTTP 400)

Validation errors occur when you use invalid field names, types, or query structures. The following query attempts to access a field named InvalidFieldName that does not exist on the ArticlePage type. This results in a validation error.

# Validation error - field doesn't exist
query GetArticles {
  ArticlePage {
    items {
      Name
      InvalidFieldName  # This field doesn't exist
    }
  }
}

The error response looks like the following:

{
  "errors": [
    {
      "message": "Cannot query field 'InvalidFieldName' on type 'ArticlePage'",
      "locations": [{"line": 5, "column": 7}],
      "extensions": {
        "code": "GRAPHQL_VALIDATION_FAILED"
      }
    }
  ]
}

Authorization errors (HTTP 401 or 403)

Authorization errors happen when authentication is missing or invalid. The following error message indicates that the query requires authentication, which is either missing or invalid. The UNAUTHENTICATED code specifies the type of authorization error.

{
  "errors": [
    {
      "message": "You must be authenticated to perform this action",
      "extensions": {
        "code": "UNAUTHENTICATED"
      }
    }
  ]
}

Performance optimization to avoid timeouts

Limit query complexity

Limit the complexity of your queries to prevent slow performance due to too many nested levels.

The first query, ComplexQuery, is inefficient because it has too many nested levels, which can lead to performance issues. The optimized version OptimizedQuery reduces the depth and uses pagination to limit the number of items returned, improving performance.

# Potentially slow - Too many nested levels
query ComplexQuery {
  ArticlePage {
    items {
      Name
      Category {
        ArticlePage {
          items {
            Name
            Category {
              ArticlePage {
                items {
                  Name
                }
              }
            }
          }
        }
      }
    }
  }
}

# Better - Limit depth and use pagination
query OptimizedQuery {
  ArticlePage(limit: 10) {
    items {
      Name
      Category {
        Name
        Description
      }
    }
  }
}

Use field selection wisely

Select the fields you need only to avoid requesting unnecessarily large fields.

The first query, InefficientQuery, requests large text fields that may not be necessary, which can slow down performance. The efficient version, EfficientQuery, requests only the fields needed for the task, reducing the data size and improving performance.

# Requesting unnecessarily large fields
query InefficinetQuery {
  ArticlePage {
    items {
      Name
      MainBody        # Large text field
      TeaserText      # Another text field
      MetaDescription # Another text field
      # ... many more fields
    }
  }
}

# Request only needed fields
query EfficientQuery {
  ArticlePage {
    items {
      Name
      RelativePath
      StartPublish
    }
  }
}

Error recovery strategies

Graceful degradation

Implement graceful degradation by using fallback options in an event of an error.

The following function tries to fetch articles from a GraphQL API. If an error occurs, it logs a warning and falls back to retrieving articles from a cache, ensuring continued functionality.

async function getArticlesWithFallback() {
  try {
    return await getArticlesFromGraph();
  } catch (error) {
    console.warn('Graph API failed, falling back to cache:', error.message);
    return await getArticlesFromCache();
  }
}

Partial data handling

Handle partial data by processing any available data, even if errors are present.

The following function checks if the result contains errors. If so, it logs a warning but continues to process any successfully returned data. This approach lets you to work with partial data rather than discarding it entirely.

function handlePartialData(result) {
  if (result.errors) {
    console.warn('Partial data received:', result.errors);
  }
  
  // Still process any data that was successfully returned
  return result.data || {};
}