SDK & Framework Guides

GraphQL Error Monitoring Guide

Understand GraphQL server error tracking for partial failures and resolver errors. Monitor field-level issues and debug production problems effectively.

GraphQL servers break differently than REST APIs. A single GraphQL request can partially succeed—returning data for some fields while errors occur in others. This field-level error model means your monitoring strategy needs to evolve. GraphQL server error tracking requires understanding resolver failures, tracking partial responses, and correlating errors across the distributed execution graph that GraphQL builds behind the scenes.

Traditional error tracking treats a request as either success or failure. GraphQL doesn't work that way. You need visibility into which resolvers threw, what data was recovered, and how deeply those errors propagated through your schema. If your database query fails while fetching a user's posts, GraphQL returns the user object intact but null for posts—and your monitoring must catch that semantic error, not just the HTTP 200.

Why GraphQL Error Tracking is Different

REST APIs return a single response per endpoint. GraphQL aggregates responses across potentially dozens of resolvers, each of which can fail independently. A client might receive 200 OK with partial data and an errors array in the same response. Missing this distinction means you'll think your API is healthy when critical fields are actually broken.

GraphQL also doesn't map neatly to HTTP status codes. A resolver throwing an error doesn't necessarily mean the HTTP response should be 5xx. Your monitoring tool needs to understand GraphQL's error envelope—the shape of the errors field in the response—and extract meaningful context about which field failed and why.

Most generic APM tools treat GraphQL like any other API, counting a request with field-level errors as a successful HTTP 200. You'll miss slow resolvers, recurring resolver failures, and the real surface area of your schema that's breaking in production.

Understanding Resolver Errors and Partial Failures

Every resolver in your schema is a potential failure point. When a resolver throws an error, GraphQL's execution engine catches it, logs the error, and sets that field to null in the response. The operation continues for sibling fields.

This means a single GraphQL query can return:

  • Some fields with correct data
  • Some fields as null due to resolver errors
  • An errors array documenting what failed
  • Metadata about where in the schema each error occurred (path, field name, parent type)

Monitoring only the HTTP status is useless. You need to parse the errors array and group errors by resolver, by field path, and by error message. A recurring error in the user.posts resolver is a signal of a database problem; an error in the post.author.avatar resolver might indicate an external API issue.

The challenge is scale: in a complex schema, you might have hundreds of resolvers. Without proper error tracking, you'll only hear about broken queries when users complain—the monitoring tool needs to automatically surface which resolvers are failing and how often.

Setting Up Error Tracking for GraphQL

Start by adding error tracking to your app. Most Sentry SDKs work with GraphQL servers out of the box because they hook into your server framework (Express, Apollo, NestJS, Django, FastAPI, etc.).

For an Apollo Server with Node.js, initialize the SDK and attach it to your ApolloServer plugin:

const Sentry = require("@sentry/node");

Sentry.init({
  dsn: "https://<key>@light-trace.robomiri.com/1",
  tracesSampleRate: 1.0,
});

const server = new ApolloServer({
  typeDefs,
  resolvers,
  plugins: {
    didResolveOperation({ request, document }) {
      // Attach operation name for grouping
      Sentry.setTag("graphql.operation", request.operationName);
    },
    didEncounterErrors(ctx) {
      // Capture all errors from resolvers
      for (const err of ctx.errors) {
        Sentry.captureException(err, {
          contexts: {
            graphql: {
              operationName: ctx.request.operationName,
              variableValues: ctx.request.variables,
            },
          },
          tags: {
            "graphql.path": err.path?.join("."),
          },
        });
      }
    },
  },
});

This captures resolver errors with schema context. If you're using NestJS error tracking or Python error tracking with GraphQL, the principle is the same: hook the error handler and enrich with field path information.

Set operation name as a tag and variable values as context. This makes errors groupable by operation and lets you correlate errors across different query patterns.

Monitoring Resolver Errors and Performance

Beyond catching errors, you need to see which resolvers are slow. GraphQL execution is sequential per field, so a slow resolver in a deeply nested part of your schema can tank overall query latency.

Use distributed tracing to instrument your resolvers:

async function resolveUser(parent, args, context) {
  const span = Sentry.startTransaction({
    op: "graphql.resolver",
    name: "User.post",
  });

  try {
    const user = await db.users.findById(args.id);
    return user;
  } catch (err) {
    span.setStatus("error");
    Sentry.captureException(err);
    throw err; // Let GraphQL handle the error envelope
  } finally {
    span.finish();
  }
}

With tracing enabled, you'll see resolver duration, database query timing, external API calls, and error chains all in a single waterfall view. How to debug production errors often requires this granular timing data—knowing that a resolver spent 30 seconds waiting on a downstream API is critical context.

Using Breadcrumbs for GraphQL Context

Breadcrumbs are timestamped events leading up to an error. In GraphQL, they're invaluable for understanding query execution.

const server = new ApolloServer({
  plugins: {
    willSendResponse(ctx) {
      Sentry.addBreadcrumb({
        category: "graphql",
        message: `Query ${ctx.request.operationName} executed`,
        level: "info",
        data: {
          variableCount: Object.keys(ctx.request.variables).length,
          fieldCount: Object.keys(ctx.response.data || {}).length,
          errorCount: ctx.response.errors?.length || 0,
        },
      });
    },
  },
});

Breadcrumbs show the execution path: which arguments were passed, how many fields were resolved before an error, whether the error was in a nested resolver. This is the detective work that turns "user.posts query is broken" into "user.posts query fails when user.id is 0 or negative."

Alerting on GraphQL Errors

Most errors in production are known issues already seen before. The critical ones are new field errors—a resolver that never failed suddenly throwing an error in production.

Set up error tracking alerts for new issues. LightTrace groups errors by fingerprint (stack trace + error type + affected field path), so a new resolver error will automatically trigger an alert. You can also set frequency thresholds: alert if a specific resolver error occurs more than 10 times in an hour.

Configure alerts in your LightTrace project to notify you via email when a new GraphQL error surfaces. For service health, monitor resolved issue rates and error trends over time—a spike in resolver errors might indicate a bad deploy or a downstream service degradation.

Best Practices for GraphQL Error Monitoring

Tag everything schema-relevant. Beyond operation name and field path, include resolver name, parent type, and argument values. This makes error grouping and filtering obvious.

Separate resolver errors from query parsing/validation errors. A malformed query and a database timeout are different problems. GraphQL distinguishes them in the response; your monitoring should too.

Monitor for null fields. A resolver that returns null silently (no error thrown) is still a failure if the field is non-nullable in your schema. Some GraphQL frameworks have plugins to detect these; others require explicit middleware.

Correlate errors with schema changes. If a resolver starts failing after a deploy, knowing what changed in that resolver is critical. Keep source maps and symbol information uploaded to your error tracker.

Sample mutations carefully. Error tracking on high-volume mutations can create noise. Use sampling to capture 1-in-100 successful mutations, but log all errors.

Don't treat "HTTP 200 with errors in the errors array" as a success. These are partial failures that degrade user experience and often indicate data corruption or missing functionality.

GraphQL error tracking is about precision: seeing which fields fail, how often, and correlating those failures with your schema, your infrastructure, and your deploys. With the right monitoring in place, you'll catch resolver bugs before users notice degraded data.

Start tracking errors in minutes

Start monitoring your GraphQL server with LightTrace. It's Sentry-compatible, so you can point your SDK there with a single DSN change. Get 5,000 events free every month and see your resolver errors, field paths, and execution timings in a fast, searchable dashboard.

Fix your next production error faster

Point any Sentry SDK at LightTrace — free up to 5,000 events/month.