STET

agent_patch

runs/2026-02-28__13-38-10__gpt-5-1-codex-mini/flux-pr-1034/flux-pr-1034.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/agent-logs/agent.patch

21650 bytes

Back to adjudication
diff --git a/tmp/agent-patch-flux-pr-1034.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/execution/engine/execution_engine.go b/app/execution/engine/execution_engine.go
index 823882f..d081826 100644
--- a/tmp/agent-patch-flux-pr-1034.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/execution/engine/execution_engine.go
+++ b/app/execution/engine/execution_engine.go
@@ -37,10 +37,11 @@ func newInternalExecutionContext() *internalExecutionContext {
 	}
 }
 
-func (e *internalExecutionContext) prepare(ctx context.Context, variables []byte, request resolve.Request) {
+func (e *internalExecutionContext) prepare(ctx context.Context, variables []byte, request resolve.Request, variableNameMapping map[string]string) {
 	e.setContext(ctx)
 	e.setVariables(variables)
 	e.setRequest(request)
+	e.setVariableNameMapping(variableNameMapping)
 }
 
 func (e *internalExecutionContext) setRequest(request resolve.Request) {
@@ -57,8 +58,13 @@ func (e *internalExecutionContext) setVariables(variables []byte) {
 	}
 }
 
+func (e *internalExecutionContext) setVariableNameMapping(mapping map[string]string) {
+	e.resolveContext.VariableNameMapping = mapping
+}
+
 func (e *internalExecutionContext) reset() {
 	e.resolveContext.Free()
+	e.resolveContext.VariableNameMapping = nil
 }
 
 type ExecutionEngine struct {
@@ -183,10 +189,22 @@ func (e *ExecutionEngine) Execute(ctx context.Context, operation *graphql.Reques
 		}
 	}
 
+	remapResult, err := operation.Normalize(e.config.schema,
+		astnormalization.WithVariableRemapping(),
+	)
+	if err != nil {
+		return err
+	} else if !remapResult.Successful {
+		return remapResult.Errors
+	}
+
+	variableNameMapping := operation.VariableNameMapping()
+
 	// Validate user-supplied and extracted variables against the operation.
 	if len(operation.Variables) > 0 && operation.Variables[0] == '{' {
 		validator := variablesvalidation.NewVariablesValidator(variablesvalidation.VariablesValidatorOptions{
 			ApolloCompatibilityFlags: e.apolloCompatibilityFlags,
+			VariableNameMapping:      variableNameMapping,
 		})
 		if err := validator.Validate(operation.Document(), e.config.schema.Document(), operation.Variables); err != nil {
 			return err
@@ -194,7 +212,7 @@ func (e *ExecutionEngine) Execute(ctx context.Context, operation *graphql.Reques
 	}
 
 	execContext := newInternalExecutionContext()
-	execContext.prepare(ctx, operation.Variables, operation.InternalRequest())
+	execContext.prepare(ctx, operation.Variables, operation.InternalRequest(), variableNameMapping)
 	for i := range options {
 		options[i](execContext)
 	}
diff --git a/tmp/agent-patch-flux-pr-1034.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/execution/graphql/normalization.go b/app/execution/graphql/normalization.go
index 62253b0..f938ec3 100644
--- a/tmp/agent-patch-flux-pr-1034.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/execution/graphql/normalization.go
+++ b/app/execution/graphql/normalization.go
@@ -22,6 +22,7 @@ func (r *Request) Normalize(schema *Schema, options ...astnormalization.Option)
 	}
 
 	r.document.Input.Variables = r.Variables
+	r.variableNameMapping = nil
 
 	// use default normalization options if none are provided
 	if len(options) == 0 {
@@ -30,6 +31,7 @@ func (r *Request) Normalize(schema *Schema, options ...astnormalization.Option)
 			astnormalization.WithRemoveFragmentDefinitions(),
 			astnormalization.WithRemoveUnusedVariables(),
 			astnormalization.WithInlineFragmentSpreads(),
+			astnormalization.WithVariableRemapping(),
 		}
 	}
 
@@ -51,6 +53,7 @@ func (r *Request) Normalize(schema *Schema, options ...astnormalization.Option)
 	r.isNormalized = true
 
 	r.Variables = r.document.Input.Variables
+	r.variableNameMapping = normalizer.VariableNameMapping().CanonicalToOriginal
 
 	return NormalizationResult{Successful: true, Errors: nil}, nil
 }
diff --git a/tmp/agent-patch-flux-pr-1034.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/execution/graphql/request.go b/app/execution/graphql/request.go
index 1e10748..c324786 100644
--- a/tmp/agent-patch-flux-pr-1034.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/execution/graphql/request.go
+++ b/app/execution/graphql/request.go
@@ -37,14 +37,19 @@ type Request struct {
 	Variables     json.RawMessage `json:"variables,omitempty"`
 	Query         string          `json:"query"`
 
-	document     ast.Document
-	isParsed     bool
-	isNormalized bool
-	request      resolve.Request
+	document            ast.Document
+	isParsed            bool
+	isNormalized        bool
+	request             resolve.Request
+	variableNameMapping map[string]string
 
 	validForSchema map[uint64]ValidationResult
 }
 
+func (r *Request) VariableNameMapping() map[string]string {
+	return r.variableNameMapping
+}
+
 func UnmarshalRequest(reader io.Reader, request *Request) error {
 	requestBytes, err := io.ReadAll(reader)
 	if err != nil {
diff --git a/tmp/agent-patch-flux-pr-1034.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/pkg/astnormalization/astnormalization.go b/app/pkg/astnormalization/astnormalization.go
index 7cb6e18..e17ed16 100644
--- a/tmp/agent-patch-flux-pr-1034.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/pkg/astnormalization/astnormalization.go
+++ b/app/pkg/astnormalization/astnormalization.go
@@ -89,10 +89,11 @@ func NormalizeNamedOperation(operation, definition *ast.Document, operationName
 
 // OperationNormalizer walks a given AST and applies all registered rules
 type OperationNormalizer struct {
-	operationWalkers     []*astvisitor.Walker
-	variablesExtraction  *variablesExtractionVisitor
-	options              options
-	definitionNormalizer *DefinitionNormalizer
+	operationWalkers         []*astvisitor.Walker
+	variablesExtraction      *variablesExtractionVisitor
+	options                  options
+	definitionNormalizer     *DefinitionNormalizer
+	variableRemappingVisitor *variablesRemappingVisitor
 }
 
 // NewNormalizer creates a new OperationNormalizer and sets up all default rules
@@ -130,6 +131,7 @@ type options struct {
 	extractVariables          bool
 	removeUnusedVariables     bool
 	normalizeDefinition       bool
+	remapVariables            bool
 }
 
 type Option func(options *options)
@@ -158,6 +160,12 @@ func WithNormalizeDefinition() Option {
 	}
 }
 
+func WithVariableRemapping() Option {
+	return func(options *options) {
+		options.remapVariables = true
+	}
+}
+
 func (o *OperationNormalizer) setupOperationWalkers() {
 	o.operationWalkers = make([]*astvisitor.Walker, 0, 4)
 
@@ -194,6 +202,19 @@ func (o *OperationNormalizer) setupOperationWalkers() {
 
 		o.operationWalkers = append(o.operationWalkers, &variablesProcessing)
 	}
+
+	if o.options.remapVariables {
+		remapWalker := astvisitor.NewWalker(48)
+		o.variableRemappingVisitor = remapVariables(&remapWalker)
+		o.operationWalkers = append(o.operationWalkers, &remapWalker)
+	}
+}
+
+func (o *OperationNormalizer) VariableNameMapping() VariableNamesMapping {
+	if o.variableRemappingVisitor == nil {
+		return VariableNamesMapping{}
+	}
+	return o.variableRemappingVisitor.Mapping()
 }
 
 func (o *OperationNormalizer) prepareDefinition(definition *ast.Document, report *operationreport.Report) {
diff --git a/app/pkg/astnormalization/variables_remapping.go b/app/pkg/astnormalization/variables_remapping.go
new file mode 100644
index 0000000..dab1338
--- /dev/null
+++ b/app/pkg/astnormalization/variables_remapping.go
@@ -0,0 +1,111 @@
+package astnormalization
+
+import (
+	"strconv"
+
+	"github.com/buger/jsonparser"
+	"github.com/tidwall/sjson"
+
+	"github.com/wundergraph/graphql-go-tools/pkg/ast"
+	"github.com/wundergraph/graphql-go-tools/pkg/astvisitor"
+)
+
+// VariableNamesMapping tracks the mapping between original variable names and their
+// canonical normalized counterparts.
+type VariableNamesMapping struct {
+	CanonicalToOriginal map[string]string
+	OriginalToCanonical map[string]string
+}
+
+type variablesRemappingVisitor struct {
+	*astvisitor.Walker
+	operation        *ast.Document
+	mapping          VariableNamesMapping
+	operationCounter map[int]int
+}
+
+func remapVariables(walker *astvisitor.Walker) *variablesRemappingVisitor {
+	visitor := &variablesRemappingVisitor{
+		Walker: walker,
+	}
+	walker.RegisterEnterDocumentVisitor(visitor)
+	walker.RegisterEnterOperationVisitor(visitor)
+	walker.RegisterEnterVariableDefinitionVisitor(visitor)
+	return visitor
+}
+
+func (v *variablesRemappingVisitor) EnterDocument(operation, definition *ast.Document) {
+	v.operation = operation
+	v.mapping = VariableNamesMapping{
+		CanonicalToOriginal: make(map[string]string),
+		OriginalToCanonical: make(map[string]string),
+	}
+	v.operationCounter = make(map[int]int)
+}
+
+func (v *variablesRemappingVisitor) EnterOperationDefinition(ref int) {
+	if v.operationCounter == nil {
+		v.operationCounter = make(map[int]int)
+	}
+	v.operationCounter[ref] = 0
+}
+
+func (v *variablesRemappingVisitor) EnterVariableDefinition(ref int) {
+	if v.operation == nil {
+		return
+	}
+	if len(v.Ancestors) == 0 || v.Ancestors[0].Kind != ast.NodeKindOperationDefinition {
+		return
+	}
+
+	operationRef := v.Ancestors[0].Ref
+	index := v.operationCounter[operationRef]
+	canonical := canonicalVariableName(index)
+	v.operationCounter[operationRef] = index + 1
+
+	variableValueRef := v.operation.VariableDefinitions[ref].VariableValue.Ref
+	oldName := v.operation.VariableValueNameString(variableValueRef)
+
+	canonicalBytes := []byte(canonical)
+	v.operation.VariableValues[variableValueRef].Name = v.operation.Input.AppendInputBytes(canonicalBytes)
+	v.renameInputVariable(oldName, canonical)
+
+	v.mapping.CanonicalToOriginal[canonical] = oldName
+	v.mapping.OriginalToCanonical[oldName] = canonical
+}
+
+func (v *variablesRemappingVisitor) Mapping() VariableNamesMapping {
+	return v.mapping
+}
+
+func (v *variablesRemappingVisitor) renameInputVariable(oldName, canonical string) {
+	if oldName == canonical {
+		return
+	}
+	value, _, _, err := jsonparser.Get(v.operation.Input.Variables, oldName)
+	if err != nil {
+		if err == jsonparser.KeyPathNotFoundError {
+			return
+		}
+		v.StopWithInternalErr(err)
+		return
+	}
+
+	variablesStr, err := sjson.Delete(string(v.operation.Input.Variables), oldName)
+	if err != nil {
+		v.StopWithInternalErr(err)
+		return
+	}
+
+	variables, err := sjson.SetRawBytes([]byte(variablesStr), canonical, value)
+	if err != nil {
+		v.StopWithInternalErr(err)
+		return
+	}
+
+	v.operation.Input.Variables = variables
+}
+
+func canonicalVariableName(index int) string {
+	return "v" + strconv.Itoa(index+1)
+}
diff --git a/tmp/agent-patch-flux-pr-1034.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/pkg/engine/resolve/resolve.go b/app/pkg/engine/resolve/resolve.go
index f6b93a0..6f80737 100644
--- a/tmp/agent-patch-flux-pr-1034.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/pkg/engine/resolve/resolve.go
+++ b/app/pkg/engine/resolve/resolve.go
@@ -117,22 +117,23 @@ type AfterFetchHook interface {
 }
 
 type Context struct {
-	ctx              context.Context
-	Variables        []byte
-	Request          Request
-	pathElements     [][]byte
-	responseElements []string
-	lastFetchID      int
-	patches          []patch
-	usedBuffers      []*bytes.Buffer
-	currentPatch     int
-	maxPatch         int
-	pathPrefix       []byte
-	dataLoader       *dataLoader
-	beforeFetchHook  BeforeFetchHook
-	afterFetchHook   AfterFetchHook
-	position         Position
-	RenameTypeNames  []RenameTypeName
+	ctx                 context.Context
+	Variables           []byte
+	Request             Request
+	VariableNameMapping map[string]string
+	pathElements        [][]byte
+	responseElements    []string
+	lastFetchID         int
+	patches             []patch
+	usedBuffers         []*bytes.Buffer
+	currentPatch        int
+	maxPatch            int
+	pathPrefix          []byte
+	dataLoader          *dataLoader
+	beforeFetchHook     BeforeFetchHook
+	afterFetchHook      AfterFetchHook
+	position            Position
+	RenameTypeNames     []RenameTypeName
 }
 
 type Request struct {
@@ -192,19 +193,28 @@ func (c *Context) clone() Context {
 		copy(patches[i].extraPath, c.patches[i].extraPath)
 		copy(patches[i].data, c.patches[i].data)
 	}
+	var mapping map[string]string
+	if len(c.VariableNameMapping) > 0 {
+		mapping = make(map[string]string, len(c.VariableNameMapping))
+		for k, v := range c.VariableNameMapping {
+			mapping[k] = v
+		}
+	}
+
 	return Context{
-		ctx:             c.ctx,
-		Variables:       variables,
-		Request:         c.Request,
-		pathElements:    pathElements,
-		patches:         patches,
-		usedBuffers:     make([]*bytes.Buffer, 0, 48),
-		currentPatch:    c.currentPatch,
-		maxPatch:        c.maxPatch,
-		pathPrefix:      pathPrefix,
-		beforeFetchHook: c.beforeFetchHook,
-		afterFetchHook:  c.afterFetchHook,
-		position:        c.position,
+		ctx:                 c.ctx,
+		Variables:           variables,
+		Request:             c.Request,
+		VariableNameMapping: mapping,
+		pathElements:        pathElements,
+		patches:             patches,
+		usedBuffers:         make([]*bytes.Buffer, 0, 48),
+		currentPatch:        c.currentPatch,
+		maxPatch:            c.maxPatch,
+		pathPrefix:          pathPrefix,
+		beforeFetchHook:     c.beforeFetchHook,
+		afterFetchHook:      c.afterFetchHook,
+		position:            c.position,
 	}
 }
 
@@ -226,6 +236,7 @@ func (c *Context) Free() {
 	c.position = Position{}
 	c.dataLoader = nil
 	c.RenameTypeNames = nil
+	c.VariableNameMapping = nil
 }
 
 func (c *Context) SetBeforeFetchHook(hook BeforeFetchHook) {
diff --git a/tmp/agent-patch-flux-pr-1034.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/pkg/graphql/execution_engine_v2.go b/app/pkg/graphql/execution_engine_v2.go
index 8ca7f3b..f2eba25 100644
--- a/tmp/agent-patch-flux-pr-1034.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/pkg/graphql/execution_engine_v2.go
+++ b/app/pkg/graphql/execution_engine_v2.go
@@ -117,10 +117,11 @@ func newInternalExecutionContext() *internalExecutionContext {
 	}
 }
 
-func (e *internalExecutionContext) prepare(ctx context.Context, variables []byte, request resolve.Request) {
+func (e *internalExecutionContext) prepare(ctx context.Context, variables []byte, request resolve.Request, variableNameMapping map[string]string) {
 	e.setContext(ctx)
 	e.setVariables(variables)
 	e.setRequest(request)
+	e.setVariableNameMapping(variableNameMapping)
 }
 
 func (e *internalExecutionContext) setRequest(request resolve.Request) {
@@ -137,6 +138,11 @@ func (e *internalExecutionContext) setVariables(variables []byte) {
 
 func (e *internalExecutionContext) reset() {
 	e.resolveContext.Free()
+	e.resolveContext.VariableNameMapping = nil
+}
+
+func (e *internalExecutionContext) setVariableNameMapping(mapping map[string]string) {
+	e.resolveContext.VariableNameMapping = mapping
 }
 
 type ExecutionEngineV2 struct {
@@ -248,6 +254,18 @@ func (e *ExecutionEngineV2) Execute(ctx context.Context, operation *Request, wri
 		}
 	}
 
+	remapResult, err := operation.Normalize(e.config.schema,
+		astnormalization.WithVariableRemapping(),
+	)
+	if err != nil {
+		return err
+	}
+	if !remapResult.Successful {
+		return remapResult.Errors
+	}
+
+	variableNameMapping := operation.VariableNameMapping()
+
 	result, err := operation.ValidateForSchema(e.config.schema)
 	if err != nil {
 		return err
@@ -259,7 +277,7 @@ func (e *ExecutionEngineV2) Execute(ctx context.Context, operation *Request, wri
 	execContext := e.getExecutionCtx()
 	defer e.putExecutionCtx(execContext)
 
-	execContext.prepare(ctx, operation.Variables, operation.request)
+	execContext.prepare(ctx, operation.Variables, operation.request, variableNameMapping)
 
 	for i := range options {
 		options[i](execContext)
diff --git a/tmp/agent-patch-flux-pr-1034.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/pkg/graphql/normalization_test.go b/app/pkg/graphql/normalization_test.go
index 10db22e..0e608ee 100644
--- a/tmp/agent-patch-flux-pr-1034.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/pkg/graphql/normalization_test.go
+++ b/app/pkg/graphql/normalization_test.go
@@ -84,6 +84,28 @@ func TestRequest_Normalize(t *testing.T) {
 }`)
 	})
 
+	t.Run("should remap variables to canonical names and record the mapping", func(t *testing.T) {
+		schema := starwarsSchema(t)
+		request := Request{
+			Query: `query Foo($userId: ID!, $status: String) {
+				droid(id: $userId) {
+					name
+				}
+				search(text: $status) {
+					... on Droid {
+						name
+					}
+				}
+			}`,
+			Variables: []byte(`{"userId":"R2D2","status":"ACTIVE"}`),
+		}
+		result, err := request.Normalize(schema)
+		require.NoError(t, err)
+		assert.True(t, result.Successful)
+		assert.Equal(t, `{"v1":"R2D2","v2":"ACTIVE"}`, string(request.document.Input.Variables))
+		assert.Equal(t, map[string]string{"v1": "userId", "v2": "status"}, request.VariableNameMapping())
+	})
+
 	t.Run("should successfully normalize query and remove unused variables", func(t *testing.T) {
 		request := Request{
 			OperationName: "MySearch",
diff --git a/tmp/agent-patch-flux-pr-1034.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/variablesvalidation/variablesvalidation.go b/app/v2/pkg/variablesvalidation/variablesvalidation.go
index 6410033..9921cb5 100644
--- a/tmp/agent-patch-flux-pr-1034.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/variablesvalidation/variablesvalidation.go
+++ b/app/v2/pkg/variablesvalidation/variablesvalidation.go
@@ -41,6 +41,7 @@ func (v *variablesVisitor) invalidEnumValueIfAllowed(variableContent string) str
 }
 
 func (v *variablesVisitor) invalidValueMessage(variableName, variableContent string) string {
+	variableName = v.variableNameStringForDisplay(variableName)
 	if v.opts.DisableExposingVariablesContent {
 		return fmt.Sprintf(`Variable "$%s" got invalid value`, variableName)
 	}
@@ -66,13 +67,15 @@ type VariablesValidator struct {
 type VariablesValidatorOptions struct {
 	ApolloCompatibilityFlags        apollocompatibility.Flags
 	DisableExposingVariablesContent bool
+	VariableNameMapping             map[string]string
 }
 
 func NewVariablesValidator(options VariablesValidatorOptions) *VariablesValidator {
 	walker := astvisitor.NewWalker(8)
 	visitor := &variablesVisitor{
-		walker: &walker,
-		opts:   options,
+		walker:              &walker,
+		opts:                options,
+		variableNameMapping: options.VariableNameMapping,
 	}
 	walker.RegisterEnterVariableDefinitionVisitor(visitor)
 	return &VariablesValidator{
@@ -106,6 +109,7 @@ type variablesVisitor struct {
 	currentVariableValue *astjson.Value
 	path                 []pathItem
 	opts                 VariablesValidatorOptions
+	variableNameMapping  map[string]string
 }
 
 func (v *variablesVisitor) renderPath() string {
@@ -215,7 +219,8 @@ func (v *variablesVisitor) renderVariableRequiredError(variableName []byte, type
 		v.err = err
 		return
 	}
-	v.err = v.newInvalidVariableError(fmt.Sprintf(`Variable "$%s" of required type "%s" was not provided.`, string(variableName), out.String()))
+	variableDisplayName := v.variableNameForDisplay(variableName)
+	v.err = v.newInvalidVariableError(fmt.Sprintf(`Variable "$%s" of required type "%s" was not provided.`, variableDisplayName, out.String()))
 }
 
 func (v *variablesVisitor) renderVariableInvalidObjectTypeError(typeName []byte, variablesNode *astjson.Value) {
@@ -294,7 +299,22 @@ func (v *variablesVisitor) renderVariableInvalidNullError(variableName []byte, t
 		return
 	}
 	typeName := buf.String()
-	v.err = v.newInvalidVariableError(fmt.Sprintf(`Variable "$%s" got invalid value null; Expected non-nullable type "%s" not to be null.`, string(variableName), typeName))
+	variableDisplayName := v.variableNameForDisplay(variableName)
+	v.err = v.newInvalidVariableError(fmt.Sprintf(`Variable "$%s" got invalid value null; Expected non-nullable type "%s" not to be null.`, variableDisplayName, typeName))
+}
+
+func (v *variablesVisitor) variableNameForDisplay(name []byte) string {
+	return v.variableNameStringForDisplay(string(name))
+}
+
+func (v *variablesVisitor) variableNameStringForDisplay(name string) string {
+	if v.variableNameMapping == nil {
+		return name
+	}
+	if mapped, ok := v.variableNameMapping[name]; ok {
+		return mapped
+	}
+	return name
 }
 
 func (v *variablesVisitor) traverseFieldDefinitionType(fieldTypeDefinitionNodeKind ast.NodeKind, fieldName ast.ByteSlice, jsonValue *astjson.Value, typeRef, inputFieldRef int) {
diff --git a/tmp/agent-patch-flux-pr-1034.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/variablesvalidation/variablesvalidation_test.go b/app/v2/pkg/variablesvalidation/variablesvalidation_test.go
index 41a911f..555959e 100644
--- a/tmp/agent-patch-flux-pr-1034.1-of-1.2026-02-28__13-38-10__gpt-5-1-codex-mini/app/v2/pkg/variablesvalidation/variablesvalidation_test.go
+++ b/app/v2/pkg/variablesvalidation/variablesvalidation_test.go
@@ -29,6 +29,20 @@ func TestVariablesValidation(t *testing.T) {
 		assert.Equal(t, `Variable "$bar" of required type "String!" was not provided.`, err.Error())
 	})
 
+	t.Run("maps canonical variable names back to original in errors", func(t *testing.T) {
+		tc := testCase{
+			schema:    `type Query { hello(id: ID!): String }`,
+			operation: `query Foo($v1: ID!) { hello(id: $v1) }`,
+			variables: `{"v1": null}`,
+		}
+		opts := VariablesValidatorOptions{
+			VariableNameMapping: map[string]string{"v1": "userId"},
+		}
+		err := runTestWithOptions(t, tc, opts)
+		require.Error(t, err)
+		assert.Contains(t, err.Error(), `"$userId"`)
+	})
+
 	t.Run("a missing required input produces an error", func(t *testing.T) {
 		tc := testCase{
 			schema:    inputSchema,