skip to content

In a GraphQL subscription, does a resolver error on one event end the response stream?

level: seniorimportance: should knowfreq 45%

answer

  1. Two error surfaces, only one fatal
  2. Per-event execution is ordinary execution
  3. Errors travel with the event, not the stream
  4. The source stream is what ends things
  5. Open, on time, and empty

basics

~20 s

No. Each event is a normal execution, so a field error is collected into that one event's errors entry and nulls propagate inside that one result. The stream keeps delivering later events. Only the underlying source stream ending or failing ends the subscription.

solid answer

~50 s

There are two error surfaces and they behave differently. An error raised while **opening** the source event stream means no subscription is created at all: the caller receives a single result carrying errors and nothing further. An error raised **during one event's execution** is handled exactly as in a query — collected into that result's `errors` entry, with null propagating to the nearest nullable position, possibly making that event's `data` null. The response stream is unaffected and the next event executes normally. What does end a subscription is the source event stream itself completing or failing, or the subscription being cancelled. Operationally this matters because a subscription that is failing every event looks identical from the outside to one that is healthy: it stays open, delivers on time, and quietly ships empty payloads until somebody measures error rate per event.

code

json · 11 lines
json
{
  "data": {
    "segmentTranslated": { "segmentId": "seg-88213", "targetText": null }
  },
  "errors": [
    {
      "message": "Translation memory backend unavailable",
      "path": ["segmentTranslated", "targetText"]
    }
  ]
}

go deeper

for a junior

Know that an error inside one event affects only that event's result: the errors entry appears alongside whatever data survived, and further events keep arriving as normal.

for a middle

Explain that per-event execution reuses the query error rules, including null propagation to the nearest nullable position, and contrast that with a subscribe-time failure that produces a single error result and no stream at all.

for a senior

Demonstrate the operational consequence: a failing subscription stays open, fast and on schedule, so health has to be measured per event. Argue why converting field errors into disconnects amplifies the original outage.

for a principal

Own the policy across feeds: where nullability sits on payload fields, what per-event error budget triggers action, and whether shedding load happens visibly at the source stream rather than invisibly one failed event at a time.

## Three places an error can appear, and only one of them is fatal Interviewers ask this because the intuition is wrong in both directions: candidates either think one bad resolver kills the feed, or they think a subscription simply cannot fail once open. The accurate picture has three surfaces. **Before any stream exists.** The document is parsed and validated first. A syntax error, an unknown field, an operation whose subscription selection set does not resolve to exactly one root field, or a missing required variable is a request error: the response is a single result with `errors` and no `data`, and no subscription is created. Nothing is streamed because nothing was subscribed. **While opening the source event stream.** The subscription root field's arguments are coerced and its event-stream resolver runs. If that raises — the upstream is unreachable, the caller is not authorized for project `tm-4417`, the filter argument is invalid — the subscribe attempt fails. The caller gets one result carrying that error and again no stream. This is the important asymmetry to state out loud: at subscribe time an error is fatal to the whole subscription, because there is nothing yet for it to be partial about. **During one event's execution.** Now the subscription exists, and per-event execution is deliberately the same algorithm a query uses — including its error handling. A resolver that raises produces a field error with a path, the field's position is nulled, and if that position is non-null the null propagates up to the nearest nullable ancestor. The result for that event is yielded with whatever `data` survived plus the `errors` entry. Then the next event executes from scratch. ```json { "data": { "segmentTranslated": { "segmentId": "seg-88213", "targetText": null } }, "errors": [ { "message": "Translation memory backend unavailable", "path": ["segmentTranslated", "targetText"] } ] } ``` If `segmentTranslated` were non-null, that same failure would null the root instead and the event would arrive as `data: null` with the same error. Either way, the response stream stays open. ## What actually ends a subscription The response stream is a mapping over the source stream, so it ends when the source ends: the source event stream completing completes the response stream, and a source stream that fails terminates it. Cancellation — the subscriber unsubscribing, or the server deciding to stop — also ends it. Notice what is *not* on that list: a resolver throwing, a non-null field bubbling to `data: null`, or a hundred consecutive events all failing. ## Why this is a senior question rather than a trivia question Because the failure is silent by design, and silence is an operational problem. A subscription whose per-event resolvers are failing continues to look perfect from every angle an ordinary dashboard watches. The stream is open. Events arrive at the expected rate. Delivery stays inside a 340 ms p99 — in fact it gets *faster*, because a failing backend call returns sooner than a successful one. Nothing reconnects, because nothing disconnected. The subscriber receives a steady rhythm of responses that arrive half-empty, and if the consuming client renders missing fields as blanks rather than checking the `errors` entry, the first report comes from a human noticing stale content. So the things to say when asked how you would run this: - **Measure per event, not per subscription.** Error rate and latency are per-event properties. A per-subscription success metric is meaningless when a subscription is a long-lived object that never reports failure. - **Decide the nullability deliberately.** A nullable payload field turns a failure into a silent hole; a non-null one turns it into `data: null` plus an error. For a feed you have to operate, loud is usually right. - **Do not convert per-event failures into disconnects.** Tearing down the subscription on a transient resolver error converts one bad event into a reconnect storm across every subscriber — an amplification of exactly the upstream problem that caused it. - **Consider a circuit at the source, not at the field.** If the upstream is genuinely down, ending or pausing the source stream is a deliberate decision with a visible signal; letting every event fail individually is the same outage with none of the signal. ## The one-line answer Field errors are per-event and non-fatal; subscribe-time errors are fatal and produce no stream; only the source stream ending, failing, or being cancelled ends the subscription.

  • A subscription is open, events arrive on time, and every payload is empty with an errors entry. What do you check first?
    Per-event error rate and the error paths, because the subscription itself is healthy by every connection-level signal. The path tells you which field is failing, and whether the failures are on the root field — pointing at event shape or authorization — or on a leaf below it, pointing at a downstream dependency. Only after that is it worth looking at the transport.
  • Should a server tear down a subscription when its per-event resolvers fail repeatedly?
    Rarely, and never automatically per error. Every teardown becomes a reconnect from that subscriber, so a downstream outage turns into a resubscribe storm on top of it. If you must shed load, do it at the source stream with an explicit, observable decision and a clear signal to the subscriber, rather than by letting individual field errors close streams.
  • Does a validation failure in the subscription document behave like a per-event error?
    No. Validation happens before anything is subscribed, so it is a request error: one result with errors, no data, and no stream. It is closer to a failed subscribe attempt than to a bad event, and clients should treat it as permanent — retrying an invalid document produces the identical failure.

saying these in an interview costs you the question

  • Says one resolver error terminates the subscription
  • Thinks an open subscription can no longer fail
  • Treats subscribe-time and per-event errors as the same
  • Assumes a failing feed will disconnect and alert itself
  • Measures subscription health only by connection uptime
  • Reconnects the subscriber on every field error

context