From 633f8c608f4d69b384e5481b9ac7942096ca9414 Mon Sep 17 00:00:00 2001 From: Yaacov Rydzinski Date: Mon, 4 May 2026 18:30:40 +0300 Subject: [PATCH 1/2] fix: name fragment variables in execution errors --- src/execution/__tests__/variables-test.ts | 30 +++++++++++++++-------- src/execution/values.ts | 14 +++++++++-- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/execution/__tests__/variables-test.ts b/src/execution/__tests__/variables-test.ts index 78d206dff9..ace1963101 100644 --- a/src/execution/__tests__/variables-test.ts +++ b/src/execution/__tests__/variables-test.ts @@ -1412,11 +1412,16 @@ describe('Execute: Handles inputs', () => { } `); - expect(result).to.have.property('errors'); - expect(result.errors).to.have.length(1); - expect(result.errors?.at(0)?.message).to.match( - /Argument "value" of required type "String!"/, - ); + expectJSON(result).toDeepEqual({ + data: null, + errors: [ + { + message: + 'Fragment "a" variable "$value" of required type "String!" was not provided.', + locations: [{ line: 3, column: 11 }], + }, + ], + }); }); it('when the definition has a default and is provided', () => { @@ -1480,11 +1485,16 @@ describe('Execute: Handles inputs', () => { } `); - expect(result).to.have.property('errors'); - expect(result.errors).to.have.length(1); - expect(result.errors?.at(0)?.message).to.match( - /Argument "value" has invalid value: Expected value of non-null type "String!" not to be null./, - ); + expectJSON(result).toDeepEqual({ + data: null, + errors: [ + { + message: + 'Fragment "a" variable "$value" has invalid value: Expected value of non-null type "String!" not to be null.', + locations: [{ line: 3, column: 23 }], + }, + ], + }); }); it('when the definition has no default and is not provided', () => { diff --git a/src/execution/values.ts b/src/execution/values.ts index 0de08bc9db..074566d9fa 100644 --- a/src/execution/values.ts +++ b/src/execution/values.ts @@ -244,7 +244,7 @@ function coerceArgument( // continue with an invalid argument value. throw new GraphQLError( // TODO: clean up the naming of isRequiredArgument(), isArgument(), and argDef if/when experimental fragment variables are merged - `Argument "${isArgument(argDef) ? argDef : argName}" of required type "${argType}" was not provided.`, + `${printArgumentOrFragmentVariable(argDef, node)} of required type "${argType}" was not provided.`, { nodes: node }, ); } @@ -291,7 +291,7 @@ function coerceArgument( argType, (error, path) => { // TODO: clean up the naming of isRequiredArgument(), isArgument(), and argDef if/when experimental fragment variables are merged - error.message = `Argument "${isArgument(argDef) ? argDef : argDef.name}" has invalid value${printPathArray( + error.message = `${printArgumentOrFragmentVariable(argDef, node)} has invalid value${printPathArray( path, )}: ${error.message}`; throw error; @@ -306,6 +306,16 @@ function coerceArgument( coercedValues[argName] = coercedValue; } +// TODO: clean up the naming of isRequiredArgument(), isArgument(), and argDef if/when experimental fragment variables are merged +function printArgumentOrFragmentVariable( + argDef: GraphQLArgument | GraphQLVariableSignature, + node: FieldNode | DirectiveNode | FragmentSpreadNode, +): string { + return isArgument(argDef) + ? `Argument "${argDef}"` + : `Fragment "${node.name.value}" variable "$${argDef.name}"`; +} + /** * Prepares an object map of argument values given a directive definition * and a AST node which may contain directives. Optionally also accepts a map From 333e50a23d8819ab60daaa01af9bea94050f698a Mon Sep 17 00:00:00 2001 From: Yaacov Rydzinski Date: Mon, 4 May 2026 20:10:41 +0300 Subject: [PATCH 2/2] tweak wording --- src/execution/__tests__/variables-test.ts | 4 ++-- src/execution/values.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/execution/__tests__/variables-test.ts b/src/execution/__tests__/variables-test.ts index ace1963101..2bd0ec7d99 100644 --- a/src/execution/__tests__/variables-test.ts +++ b/src/execution/__tests__/variables-test.ts @@ -1417,7 +1417,7 @@ describe('Execute: Handles inputs', () => { errors: [ { message: - 'Fragment "a" variable "$value" of required type "String!" was not provided.', + 'Variable "$value" defined by fragment "a" of required type "String!" was not provided.', locations: [{ line: 3, column: 11 }], }, ], @@ -1490,7 +1490,7 @@ describe('Execute: Handles inputs', () => { errors: [ { message: - 'Fragment "a" variable "$value" has invalid value: Expected value of non-null type "String!" not to be null.', + 'Variable "$value" defined by fragment "a" has invalid value: Expected value of non-null type "String!" not to be null.', locations: [{ line: 3, column: 23 }], }, ], diff --git a/src/execution/values.ts b/src/execution/values.ts index 074566d9fa..ce5fd6f78d 100644 --- a/src/execution/values.ts +++ b/src/execution/values.ts @@ -313,7 +313,7 @@ function printArgumentOrFragmentVariable( ): string { return isArgument(argDef) ? `Argument "${argDef}"` - : `Fragment "${node.name.value}" variable "$${argDef.name}"`; + : `Variable "$${argDef.name}" defined by fragment "${node.name.value}"`; } /**