diff --git a/src/error/__tests__/locatedError-test.ts b/src/error/__tests__/locatedError-test.ts index 21e858e95e..2e35723ac2 100644 --- a/src/error/__tests__/locatedError-test.ts +++ b/src/error/__tests__/locatedError-test.ts @@ -16,6 +16,17 @@ describe('locatedError', () => { expect(locatedError(e, [], [])).to.deep.equal(e); }); + it('wraps non-errors', () => { + const testObject = Object.freeze({}); + const error = locatedError(testObject, [], []); + + expect(error).to.be.instanceOf(GraphQLError); + expect(error.originalError).to.include({ + name: 'NonErrorThrown', + thrownValue: testObject, + }); + }); + it('passes GraphQLError-ish through', () => { const e = new Error(); // @ts-expect-error diff --git a/src/error/locatedError.ts b/src/error/locatedError.ts index fb5df58ec7..2fec320422 100644 --- a/src/error/locatedError.ts +++ b/src/error/locatedError.ts @@ -1,5 +1,5 @@ -import { inspect } from '../jsutils/inspect'; import type { Maybe } from '../jsutils/Maybe'; +import { toError } from '../jsutils/toError'; import type { ASTNode } from '../language/ast'; @@ -15,11 +15,7 @@ export function locatedError( nodes: ASTNode | ReadonlyArray | undefined | null, path?: Maybe>, ): GraphQLError { - // Sometimes a non-error is thrown, wrap it as an Error instance to ensure a consistent Error interface. - const originalError: Error | GraphQLError = - rawOriginalError instanceof Error - ? rawOriginalError - : new Error('Unexpected error value: ' + inspect(rawOriginalError)); + const originalError = toError(rawOriginalError); // Note: this uses a brand-check to support GraphQL errors originating from other contexts. if (isLocatedGraphQLError(originalError)) { diff --git a/src/jsutils/toError.ts b/src/jsutils/toError.ts new file mode 100644 index 0000000000..8d562273d6 --- /dev/null +++ b/src/jsutils/toError.ts @@ -0,0 +1,20 @@ +import { inspect } from './inspect'; + +/** + * Sometimes a non-error is thrown, wrap it as an Error instance to ensure a consistent Error interface. + */ +export function toError(thrownValue: unknown): Error { + return thrownValue instanceof Error + ? thrownValue + : new NonErrorThrown(thrownValue); +} + +class NonErrorThrown extends Error { + thrownValue: unknown; + + constructor(thrownValue: unknown) { + super('Unexpected error value: ' + inspect(thrownValue)); + this.name = 'NonErrorThrown'; + this.thrownValue = thrownValue; + } +}