Skip to content

Commit

Permalink
Fix error message generation (#10411)
Browse files Browse the repository at this point in the history
* Fix error message generation

ApolloError.graphQLErrors is typed as an array of GraphQLError in typescript, but it can actually contain any value
at runtime, including null. This is even explicitly tested: https://github.com/apollographql/apollo-client/blob/caba6c191dcb7bee265d62aba131727c5536f4ef/src/core/__tests__/QueryManager/index.ts#L369-L376

This PR simplifies error message generation, and prevents ever creating the string 'undefined' as an error message.

See: #10394

* fix: handle protocolErrors

* chore: add changeset

---------

Co-authored-by: alessia <alessia@apollographql.com>
  • Loading branch information
lovasoa and alessbell authored Mar 31, 2023
1 parent 0ca3c79 commit 152baac
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 26 deletions.
5 changes: 5 additions & 0 deletions .changeset/heavy-carpets-chew.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@apollo/client": patch
---

Simplify error message generation and make 'undefined' an impossible message string.
37 changes: 11 additions & 26 deletions src/errors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import '../utilities/globals';

import { GraphQLError, GraphQLErrorExtensions } from 'graphql';

import { isNonEmptyArray } from '../utilities';
import { isNonNullObject } from '../utilities';
import { ServerParseError } from '../link/http';
import { ServerError } from '../link/utils';
import { FetchResult } from "../link/core";
Expand Down Expand Up @@ -51,31 +51,16 @@ export function isApolloError(err: Error): err is ApolloError {
// If the error message has already been set through the
// constructor or otherwise, this function is a nop.
const generateErrorMessage = (err: ApolloError) => {
let message = '';
// If we have GraphQL errors present, add that to the error message.
if (
isNonEmptyArray(err.graphQLErrors) ||
isNonEmptyArray(err.clientErrors) ||
isNonEmptyArray(err.protocolErrors)
) {
const errors = ((err.graphQLErrors || []) as readonly Error[])
.concat(err.clientErrors || [])
.concat((err.protocolErrors || []) as readonly Error[]);
errors.forEach((error: Error) => {
const errorMessage = error
? error.message
: 'Error message not found.';
message += `${errorMessage}\n`;
});
}

if (err.networkError) {
message += `${err.networkError.message}\n`;
}

// strip newline from the end of the message
message = message.replace(/\n$/, '');
return message;
const errors = [
...err.graphQLErrors,
...err.clientErrors,
...err.protocolErrors
];
if (err.networkError) errors.push(err.networkError);
return errors
// The rest of the code sometimes unsafely types non-Error objects as GraphQLErrors
.map(err => isNonNullObject(err) && err.message || 'Error message not found.')
.join('\n');
};

export type GraphQLErrors = ReadonlyArray<GraphQLError>;
Expand Down

0 comments on commit 152baac

Please sign in to comment.