Skip to content

Commit

Permalink
Replace actual server-side error with generic "server error" message
Browse files Browse the repository at this point in the history
Reviewed By: captbaritone

Differential Revision: D63282197

fbshipit-source-id: 698c9659936b0a124a02cdee11fa88b976c0b8b4
  • Loading branch information
itamark authored and facebook-github-bot committed Sep 27, 2024
1 parent dcafff7 commit 6a038d0
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 17 deletions.
13 changes: 9 additions & 4 deletions packages/relay-runtime/store/RelayErrorTrie.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,28 @@ import type {PayloadError} from '../network/RelayNetworkTypes';
const SELF: Self = Symbol('$SELF');

class RelayFieldError extends Error {
constructor(message: string, errors: Array<TRelayFieldError> = []) {
constructor(message: string, errors: Array<TRelayFieldErrorForDisplay> = []) {
super(message);
this.name = 'RelayFieldError';
this.message = message;
this.errors = errors;
}
errors: Array<TRelayFieldError>;
errors: Array<TRelayFieldErrorForDisplay>;
}

export opaque type Self = typeof SELF;

export type TRelayFieldError = $ReadOnly<{
message: string,
export type TRelayFieldErrorForDisplay = $ReadOnly<{
path?: $ReadOnlyArray<string | number>,
severity?: 'CRITICAL' | 'ERROR' | 'WARNING',
}>;

// We display a subset of the TRelayFieldError to the user. Removing the message by default.
export type TRelayFieldError = $ReadOnly<{
...TRelayFieldErrorForDisplay,
message: string,
}>;

/**
* This is a highly-specialized data structure that is designed
* to store the field errors of a GraphQL response in such a way
Expand Down
5 changes: 3 additions & 2 deletions packages/relay-runtime/store/RelayReader.js
Original file line number Diff line number Diff line change
Expand Up @@ -340,11 +340,12 @@ class RelayReader {
let errors = this._errorResponseFields?.map(error => {
switch (error.kind) {
case 'relay_field_payload.error':
return error.error;
const {message, ...displayError} = error.error;
return displayError;
case 'missing_expected_data.throw':
case 'missing_expected_data.log':
return {
message: `Relay: Missing data for one or more fields in ${error.owner}`,
path: error.fieldPath.split('.'),
};
default:
(error.kind: empty);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ describe('RelayReader @catch', () => {
ok: false,
errors: [
{
message: 'There was an error!',
path: ['me', 'lastName'],
},
],
Expand Down Expand Up @@ -394,7 +393,6 @@ describe('RelayReader @catch', () => {
ok: false,
errors: [
{
message: 'There was an error!',
path: ['me', 'lastName'],
},
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,14 +157,16 @@ describe('RelayReader error fields', () => {
const operation = createOperationDescriptor(FooQuery, {size: 42});
const {data, errorResponseFields} = read(source, operation.fragment);

// we have a task out for adding path to missingData. Meantime that array is empty.
expect(data).toEqual({
me: {
ok: false,
errors: [
{message: 'There was an error!', path: ['me', 'lastName']},
{
message:
'Relay: Missing data for one or more fields in RelayReaderRelayErrorHandlingTest3Query',
path: ['me', 'lastName'],
},
{
path: [''],
},
],
},
Expand Down
14 changes: 8 additions & 6 deletions packages/relay-runtime/util/handlePotentialSnapshotErrors.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

'use strict';

import type {TRelayFieldError} from '../store/RelayErrorTrie';
import type {TRelayFieldErrorForDisplay} from '../store/RelayErrorTrie';
import type {
ErrorResponseFields,
IEnvironment,
Expand All @@ -37,7 +37,7 @@ function handleResolverErrors(
) {
throw new RelayFieldError(
`Relay: Unexpected resolver exception`,
relayResolverErrors.map(e => ({message: e.error.message})),
relayResolverErrors.map(e => ({path: e.fieldPath.split('.')})),
);
}
}
Expand All @@ -58,14 +58,16 @@ function handleFieldErrors(
if (shouldThrow) {
throw new RelayFieldError(
`Relay: Unexpected response payload - this object includes an errors property in which you can access the underlying errors`,
errorResponseFields.map((event): TRelayFieldError => {
errorResponseFields.map((event): TRelayFieldErrorForDisplay => {
switch (event.kind) {
case 'relay_field_payload.error':
return event.error;
//TODO: [relay] Provide a payloadErrorResolver to allow exposing custom error shape.
const {message, ...displayError} = event.error;
return displayError;
case 'missing_expected_data.throw':
return {message: 'Missing expected data'};
return {path: event.fieldPath.split('.')};
case 'missing_expected_data.log':
return {message: 'Missing expected data'};
return {path: event.fieldPath.split('.')};
default:
(event.kind: empty);
throw new Error('Relay: Unexpected event kind');
Expand Down

0 comments on commit 6a038d0

Please sign in to comment.