Skip to main content
Version: Next 🚧

Error Handling

Just like GraphQL servers, Relay Resolvers support field-level error handling. If an individual resolver throws an error, when that field is read, Relay will log that error to the environment's user-provided relayFieldLogger logger, and the field will become null.

This provides important symmetry with GraphQL servers. Resolvers are designed to enable a smooth migration path to allow teams to start with fields defined client-side using Resolvers and then eventually migrate them to a server.

If a resolver throws an error, Relay will log the error to the user-provided error logger, and will return null for the field which the resolver defines. To enable this behavior at runtime, the Relay compiler will not allow resolver fields to be typed as non-nullable.

The object passed to the relayFieldLogger will have the following shape:

type ResolverErrorEvent = {
kind: 'relay_resolver.error',
// The name of the fragment/query in which the field was read
owner: string,
// The path from the owner root to the field which threw the error
fieldPath: string,
// The error thrown by the resolver
error: Error,
}

An example logger might look like:

function fieldLogger(event) {
if(event.kind === "relay_resolver.error") {
// Log this somewhere!
console.warn(`Resolver error encountered in ${event.owner}.${event.fieldPath}`)
console.warn(event.error)
}
}

const environment = new Environment({
network: Network.create(/* your fetch function here */),
store: new RelayModernStore(new RecordSource()),
relayFieldLogger: fieldLogger
});
note

Live Resolvers can potentially throw errors when they are first evaluated or when their .read() method is called. Both types of errors will be handled identically by Relay.

Support for Semantic Nullability​

Relay resolver fields can be specified as semantically non-null just like server schema fields. Developers can add the directive @semanticNonNull in the docblock of a relay resolver in order to indicate that the field is non-nullable in the semantic sense, but that the client should still be prepared to handle errors.

For example:

/**
* @RelayResolver RelayExample.semantic_non_null_field: String @semanticNonNull
*/
export function semantic_non_null_field(
model: RelayExampleModel,
): string {
return model.someField ?? 'field was null, this is the default';
}