agent_patch
runs/2026-02-28__13-38-10__gpt-5-3-codex/flux-pr-1099/flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/agent-logs/agent.patch
68382 bytes
diff --git a/tmp/agent-patch-flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/pkg/astvalidation/operation_rule_valid_arguments.go b/app/pkg/astvalidation/operation_rule_valid_arguments.go
index f352260..3f216ac 100644
--- a/tmp/agent-patch-flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/pkg/astvalidation/operation_rule_valid_arguments.go
+++ b/app/pkg/astvalidation/operation_rule_valid_arguments.go
@@ -1,184 +1,9 @@
package astvalidation
-import (
- "bytes"
- "fmt"
+import "github.com/wundergraph/graphql-go-tools/pkg/astvisitor"
- "github.com/wundergraph/graphql-go-tools/pkg/ast"
- "github.com/wundergraph/graphql-go-tools/pkg/astvisitor"
- "github.com/wundergraph/graphql-go-tools/pkg/operationreport"
-)
-
-// ValidArguments validates if arguments are valid: values and variables has compatible types
-// deep variables comparison is handled by Values
+// ValidArguments is deprecated.
+// Variable argument type checks are validated by Values().
func ValidArguments() Rule {
- return func(walker *astvisitor.Walker) {
- visitor := validArgumentsVisitor{
- Walker: walker,
- }
- walker.RegisterEnterDocumentVisitor(&visitor)
- walker.RegisterEnterArgumentVisitor(&visitor)
- }
-}
-
-type validArgumentsVisitor struct {
- *astvisitor.Walker
- operation, definition *ast.Document
-}
-
-func (v *validArgumentsVisitor) EnterDocument(operation, definition *ast.Document) {
- v.operation = operation
- v.definition = definition
-}
-
-func (v *validArgumentsVisitor) EnterArgument(ref int) {
- definitionRef, exists := v.ArgumentInputValueDefinition(ref)
-
- if !exists {
- return
- }
-
- value := v.operation.ArgumentValue(ref)
- v.validateIfValueSatisfiesInputFieldDefinition(value, definitionRef)
-}
-
-func (v *validArgumentsVisitor) validateIfValueSatisfiesInputFieldDefinition(value ast.Value, inputValueDefinitionRef int) {
- var (
- satisfied bool
- operationTypeRef int
- variableDefinitionRef int
- )
-
- switch value.Kind {
- case ast.ValueKindVariable:
- satisfied, operationTypeRef, variableDefinitionRef = v.variableValueSatisfiesInputValueDefinition(value.Ref, inputValueDefinitionRef)
- case ast.ValueKindEnum,
- ast.ValueKindNull,
- ast.ValueKindBoolean,
- ast.ValueKindInteger,
- ast.ValueKindString,
- ast.ValueKindFloat,
- ast.ValueKindObject,
- ast.ValueKindList:
- // this types of values are covered by Values() / valuesVisitor
- return
- default:
- v.StopWithInternalErr(fmt.Errorf("validateIfValueSatisfiesInputFieldDefinition: not implemented for value.Kind: %s", value.Kind))
- return
- }
-
- if satisfied {
- return
- }
-
- if operationTypeRef == ast.InvalidRef {
- // variable is not defined on operation
- return
- }
-
- printedValue, err := v.operation.PrintValueBytes(value, nil)
- if v.HandleInternalErr(err) {
- return
- }
-
- typeRef := v.definition.InputValueDefinitionType(inputValueDefinitionRef)
- expectedTypeName, err := v.definition.PrintTypeBytes(typeRef, nil)
- if v.HandleInternalErr(err) {
- return
- }
-
- actualTypeName, err := v.operation.PrintTypeBytes(operationTypeRef, nil)
- if v.HandleInternalErr(err) {
- return
- }
-
- v.StopWithExternalErr(operationreport.ErrVariableTypeDoesntSatisfyInputValueDefinition(printedValue, actualTypeName, expectedTypeName, value.Position, v.operation.VariableDefinitions[variableDefinitionRef].VariableValue.Position))
-}
-
-func (v *validArgumentsVisitor) variableValueSatisfiesInputValueDefinition(variableValue, inputValueDefinition int) (satisfies bool, operationTypeRef int, variableDefRef int) {
- variableDefinitionRef, exists := v.variableDefinition(variableValue)
- if !exists {
- return false, ast.InvalidRef, variableDefinitionRef
- }
-
- operationTypeRef = v.operation.VariableDefinitions[variableDefinitionRef].Type
- definitionTypeRef := v.definition.InputValueDefinitions[inputValueDefinition].Type
-
- hasDefaultValue := v.validDefaultValue(v.operation.VariableDefinitions[variableDefinitionRef].DefaultValue) ||
- v.validDefaultValue(v.definition.InputValueDefinitions[inputValueDefinition].DefaultValue)
-
- return v.operationTypeSatisfiesDefinitionType(operationTypeRef, definitionTypeRef, hasDefaultValue), operationTypeRef, variableDefinitionRef
-}
-
-func (v *validArgumentsVisitor) variableDefinition(variableValueRef int) (ref int, exists bool) {
- variableName := v.operation.VariableValueNameBytes(variableValueRef)
-
- if v.Ancestors[0].Kind == ast.NodeKindOperationDefinition {
- return v.operation.VariableDefinitionByNameAndOperation(v.Ancestors[0].Ref, variableName)
- }
-
- for opDefRef := 0; opDefRef < len(v.operation.OperationDefinitions); opDefRef++ {
- ref, exists = v.operation.VariableDefinitionByNameAndOperation(opDefRef, variableName)
- if exists {
- return
- }
- }
-
- return ast.InvalidRef, false
-}
-
-func (v *validArgumentsVisitor) validDefaultValue(value ast.DefaultValue) bool {
- return value.IsDefined && value.Value.Kind != ast.ValueKindNull
-}
-
-func (v *validArgumentsVisitor) operationTypeSatisfiesDefinitionType(operationTypeRef int, definitionTypeRef int, hasDefaultValue bool) bool {
- opKind := v.operation.Types[operationTypeRef].TypeKind
- defKind := v.definition.Types[definitionTypeRef].TypeKind
-
- // A nullable op type is compatible with a non-null def type if the def has
- // a default value. Strip the def non-null and continue comparing. This
- // logic is only valid before any unnesting of types occurs, which is why
- // it's outside the for loop below.
- //
- // Example:
- // Op: someField(arg: Boolean): String
- // Def: someField(arg: Boolean! = false): String # Boolean! -> Boolean
- if opKind != ast.TypeKindNonNull && defKind == ast.TypeKindNonNull && hasDefaultValue {
- definitionTypeRef = v.definition.Types[definitionTypeRef].OfType
- }
-
- // Unnest the op and def arg types until a named type is reached,
- // then compare.
- for {
- if operationTypeRef == -1 || definitionTypeRef == -1 {
- return false
- }
- opKind = v.operation.Types[operationTypeRef].TypeKind
- defKind = v.definition.Types[definitionTypeRef].TypeKind
-
- // If the op arg type is stricter than the def arg type, that's okay.
- // Strip the op non-null and continue comparing.
- //
- // Example:
- // Op: someField(arg: Boolean!): String # Boolean! -> Boolean
- // Def: someField(arg: Boolean): String
- if opKind == ast.TypeKindNonNull && defKind != ast.TypeKindNonNull {
- operationTypeRef = v.operation.Types[operationTypeRef].OfType
- continue
- }
-
- if opKind != defKind {
- return false
- }
- if opKind == ast.TypeKindNamed {
- // defKind is also a named type because at this point both kinds
- // are the same! Compare the names.
-
- return bytes.Equal(v.operation.Input.ByteSlice(v.operation.Types[operationTypeRef].Name),
- v.definition.Input.ByteSlice(v.definition.Types[definitionTypeRef].Name))
- }
- // Both types are non-null or list. Unnest and continue comparing.
- operationTypeRef = v.operation.Types[operationTypeRef].OfType
- definitionTypeRef = v.definition.Types[definitionTypeRef].OfType
- }
+ return func(walker *astvisitor.Walker) {}
}
diff --git a/tmp/agent-patch-flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/pkg/astvalidation/operation_rule_values.go b/app/pkg/astvalidation/operation_rule_values.go
index 3ae503a..bc34596 100644
--- a/tmp/agent-patch-flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/pkg/astvalidation/operation_rule_values.go
+++ b/app/pkg/astvalidation/operation_rule_values.go
@@ -43,27 +43,13 @@ func (v *valuesVisitor) EnterVariableDefinition(ref int) {
func (v *valuesVisitor) EnterArgument(ref int) {
- definition, exists := v.ArgumentInputValueDefinition(ref)
+ inputValueDefinitionRef, exists := v.ArgumentInputValueDefinition(ref)
if !exists {
return
}
value := v.operation.ArgumentValue(ref)
- if value.Kind == ast.ValueKindVariable {
- variableName := v.operation.VariableValueNameBytes(value.Ref)
- variableDefinition, exists := v.operation.VariableDefinitionByNameAndOperation(v.Ancestors[0].Ref, variableName)
- if !exists {
- operationName := v.operation.OperationDefinitionNameBytes(v.Ancestors[0].Ref)
- v.StopWithExternalErr(operationreport.ErrVariableNotDefinedOnOperation(variableName, operationName))
- return
- }
- if !v.operation.VariableDefinitions[variableDefinition].DefaultValue.IsDefined {
- return // variable has no default value, deep type check not required
- }
- value = v.operation.VariableDefinitions[variableDefinition].DefaultValue.Value
- }
-
- v.valueSatisfiesInputValueDefinitionType(value, v.definition.InputValueDefinitions[definition].Type)
+ v.valueSatisfiesInputValueDefinition(value, inputValueDefinitionRef)
}
func (v *valuesVisitor) valueSatisfiesOperationType(value ast.Value, operationTypeRef int) bool {
@@ -151,7 +137,19 @@ func (v *valuesVisitor) valueSatisfiesOperationListType(value ast.Value, operati
return valid
}
-func (v *valuesVisitor) valueSatisfiesInputValueDefinitionType(value ast.Value, definitionTypeRef int) bool {
+func (v *valuesVisitor) valueSatisfiesInputValueDefinition(value ast.Value, inputValueDefinitionRef int) bool {
+ return v.valueSatisfiesInputValueDefinitionType(
+ value,
+ v.definition.InputValueDefinitions[inputValueDefinitionRef].Type,
+ v.validDefaultValue(v.definition.InputValueDefinitions[inputValueDefinitionRef].DefaultValue),
+ )
+}
+
+func (v *valuesVisitor) valueSatisfiesInputValueDefinitionType(value ast.Value, definitionTypeRef int, hasLocationDefaultValue bool) bool {
+ if value.Kind == ast.ValueKindVariable {
+ return v.variableValueSatisfiesInputValueDefinitionType(value, definitionTypeRef, hasLocationDefaultValue)
+ }
+
switch v.definition.Types[definitionTypeRef].TypeKind {
case ast.TypeKindNonNull:
return v.valuesSatisfiesNonNullType(value, definitionTypeRef)
@@ -166,29 +164,11 @@ func (v *valuesVisitor) valueSatisfiesInputValueDefinitionType(value ast.Value,
}
func (v *valuesVisitor) valuesSatisfiesNonNullType(value ast.Value, definitionTypeRef int) bool {
- switch value.Kind {
- case ast.ValueKindNull:
+ if value.Kind == ast.ValueKindNull {
v.handleUnexpectedNullError(value, definitionTypeRef)
return false
- case ast.ValueKindVariable:
- variableDefinitionRef, variableTypeRef, _, ok := v.operationVariableType(value.Ref)
- if !ok {
- v.handleTypeError(value, definitionTypeRef)
- return false
- }
-
- if v.operation.VariableDefinitionHasDefaultValue(variableDefinitionRef) {
- return v.valueSatisfiesInputValueDefinitionType(v.operation.VariableDefinitions[variableDefinitionRef].DefaultValue.Value, definitionTypeRef)
- }
-
- importedDefinitionType := v.importer.ImportType(definitionTypeRef, v.definition, v.operation)
- if !v.operation.TypesAreEqualDeep(importedDefinitionType, variableTypeRef) {
- v.handleVariableHasIncompatibleTypeError(value, definitionTypeRef)
- return false
- }
- return true
}
- return v.valueSatisfiesInputValueDefinitionType(value, v.definition.Types[definitionTypeRef].OfType)
+ return v.valueSatisfiesInputValueDefinitionType(value, v.definition.Types[definitionTypeRef].OfType, false)
}
func (v *valuesVisitor) valuesSatisfiesNamedType(value ast.Value, definitionTypeRef int) bool {
@@ -208,38 +188,12 @@ func (v *valuesVisitor) valuesSatisfiesNamedType(value ast.Value, definitionType
}
func (v *valuesVisitor) valueSatisfiesListType(value ast.Value, definitionTypeRef int, listItemType int) bool {
-
- if value.Kind == ast.ValueKindVariable {
- variableDefinitionRef, actualType, _, ok := v.operationVariableType(value.Ref)
- if !ok {
- v.handleTypeError(value, definitionTypeRef)
- return false
- }
-
- if v.operation.VariableDefinitionHasDefaultValue(variableDefinitionRef) {
- return v.valueSatisfiesInputValueDefinitionType(v.operation.VariableDefinitions[variableDefinitionRef].DefaultValue.Value, definitionTypeRef)
- }
-
- expectedType := v.importer.ImportType(listItemType, v.definition, v.operation)
- if v.operation.Types[actualType].TypeKind == ast.TypeKindNonNull {
- actualType = v.operation.Types[actualType].OfType
- }
- if v.operation.Types[actualType].TypeKind == ast.TypeKindList {
- actualType = v.operation.Types[actualType].OfType
- }
- if !v.operation.TypesAreEqualDeep(expectedType, actualType) {
- v.handleVariableHasIncompatibleTypeError(value, definitionTypeRef)
- return false
- }
- return true
- }
-
if value.Kind == ast.ValueKindNull {
return true
}
if value.Kind != ast.ValueKindList {
- return v.valueSatisfiesInputValueDefinitionType(value, listItemType)
+ return v.valueSatisfiesInputValueDefinitionType(value, listItemType, false)
}
if v.definition.Types[listItemType].TypeKind == ast.TypeKindNonNull {
@@ -254,7 +208,7 @@ func (v *valuesVisitor) valueSatisfiesListType(value ast.Value, definitionTypeRe
for _, i := range v.operation.ListValues[value.Ref].Refs {
listValue := v.operation.Value(i)
- if !v.valueSatisfiesInputValueDefinitionType(listValue, listItemType) {
+ if !v.valueSatisfiesInputValueDefinitionType(listValue, listItemType, false) {
valid = false
}
}
@@ -275,11 +229,6 @@ func (v *valuesVisitor) valueSatisfiesTypeDefinitionNode(value ast.Value, defini
}
func (v *valuesVisitor) valueSatisfiesEnum(value ast.Value, definitionTypeRef int, node ast.Node) bool {
- if value.Kind == ast.ValueKindVariable {
- expectedTypeName := node.NameBytes(v.definition)
- return v.variableValueHasMatchingTypeName(value, definitionTypeRef, expectedTypeName)
- }
-
if value.Kind != ast.ValueKindEnum {
v.handleUnexpectedEnumValueError(value, definitionTypeRef)
return false
@@ -297,10 +246,6 @@ func (v *valuesVisitor) valueSatisfiesEnum(value ast.Value, definitionTypeRef in
func (v *valuesVisitor) valueSatisfiesScalar(value ast.Value, definitionTypeRef int, scalar int) bool {
scalarName := v.definition.ScalarTypeDefinitionNameBytes(scalar)
- if value.Kind == ast.ValueKindVariable {
- return v.variableValueHasMatchingTypeName(value, definitionTypeRef, scalarName)
- }
-
switch {
case bytes.Equal(scalarName, literal.ID):
return v.valueSatisfiesScalarID(value, definitionTypeRef)
@@ -408,11 +353,6 @@ func (v *valuesVisitor) valueSatisfiesScalarString(value ast.Value, definitionTy
}
func (v *valuesVisitor) valueSatisfiesInputObjectTypeDefinition(value ast.Value, definitionTypeRef int, inputObjectTypeDefinition int) bool {
- if value.Kind == ast.ValueKindVariable {
- expectedTypeName := v.definition.InputObjectTypeDefinitionNameBytes(inputObjectTypeDefinition)
- return v.variableValueHasMatchingTypeName(value, definitionTypeRef, expectedTypeName)
- }
-
if value.Kind != ast.ValueKindObject {
v.handleNotObjectTypeError(value, definitionTypeRef)
return false
@@ -495,12 +435,11 @@ func (v *valuesVisitor) objectFieldDefined(objectField, inputObjectTypeDefinitio
func (v *valuesVisitor) objectValueSatisfiesInputValueDefinition(objectValue ast.Value, inputObjectDefinition, inputValueDefinition int) bool {
name := v.definition.InputValueDefinitionNameBytes(inputValueDefinition)
- definitionTypeRef := v.definition.InputValueDefinitionType(inputValueDefinition)
for _, i := range v.operation.ObjectValues[objectValue.Ref].Refs {
if bytes.Equal(name, v.operation.ObjectFieldNameBytes(i)) {
value := v.operation.ObjectFieldValue(i)
- return v.valueSatisfiesInputValueDefinitionType(value, definitionTypeRef)
+ return v.valueSatisfiesInputValueDefinition(value, inputValueDefinition)
}
}
@@ -513,25 +452,6 @@ func (v *valuesVisitor) objectValueSatisfiesInputValueDefinition(objectValue ast
return true
}
-func (v *valuesVisitor) variableValueHasMatchingTypeName(value ast.Value, definitionTypeRef int, expectedTypeName []byte) bool {
- variableDefinitionRef, _, actualTypeName, ok := v.operationVariableType(value.Ref)
- if !ok {
- v.handleVariableHasIncompatibleTypeError(value, definitionTypeRef)
- return false
- }
-
- if v.operation.VariableDefinitionHasDefaultValue(variableDefinitionRef) {
- return v.valueSatisfiesInputValueDefinitionType(v.operation.VariableDefinitions[variableDefinitionRef].DefaultValue.Value, definitionTypeRef)
- }
-
- if !bytes.Equal(actualTypeName, expectedTypeName) {
- v.handleVariableHasIncompatibleTypeError(value, definitionTypeRef)
- return false
- }
-
- return true
-}
-
func (v *valuesVisitor) handleTypeError(value ast.Value, definitionTypeRef int) {
printedValue, printedType, ok := v.printValueAndUnderlyingType(value, definitionTypeRef)
if !ok {
@@ -588,11 +508,16 @@ func (v *valuesVisitor) handleVariableHasIncompatibleTypeError(value ast.Value,
return
}
- variableDefinitionRef, _, actualTypeName, ok := v.operationVariableType(value.Ref)
+ variableDefinitionRef, variableTypeRef, ok := v.operationVariableType(value.Ref)
if !ok {
return
}
+ actualTypeName, err := v.operation.PrintTypeBytes(variableTypeRef, nil)
+ if v.HandleInternalErr(err) {
+ return
+ }
+
v.Report.AddExternalError(operationreport.ErrVariableTypeDoesntSatisfyInputValueDefinition(
printedValue,
actualTypeName,
@@ -704,14 +629,71 @@ func (v *valuesVisitor) operationVariableDefinition(variableValueRef int) (ref i
return ast.InvalidRef, false
}
-func (v *valuesVisitor) operationVariableType(variableValueRef int) (variableDefinitionRef int, variableTypeRef int, typeName ast.ByteSlice, ok bool) {
+func (v *valuesVisitor) operationVariableType(variableValueRef int) (variableDefinitionRef int, variableTypeRef int, ok bool) {
variableDefRef, exists := v.operationVariableDefinition(variableValueRef)
if !exists {
- return ast.InvalidRef, ast.InvalidRef, nil, false
+ return ast.InvalidRef, ast.InvalidRef, false
}
variableTypeRef = v.operation.VariableDefinitions[variableDefRef].Type
- typeName = v.operation.ResolveTypeNameBytes(variableTypeRef)
- return variableDefRef, variableTypeRef, typeName, true
+ return variableDefRef, variableTypeRef, true
+}
+
+func (v *valuesVisitor) validDefaultValue(value ast.DefaultValue) bool {
+ return value.IsDefined && value.Value.Kind != ast.ValueKindNull
+}
+
+func (v *valuesVisitor) variableValueSatisfiesInputValueDefinitionType(value ast.Value, definitionTypeRef int, hasLocationDefaultValue bool) bool {
+ variableDefinitionRef, variableTypeRef, ok := v.operationVariableType(value.Ref)
+ if !ok {
+ variableName := v.operation.VariableValueNameBytes(value.Ref)
+ operationName := v.operation.OperationDefinitionNameBytes(v.Ancestors[0].Ref)
+ v.StopWithExternalErr(operationreport.ErrVariableNotDefinedOnOperation(variableName, operationName))
+ return false
+ }
+
+ importedDefinitionType := v.importer.ImportType(definitionTypeRef, v.definition, v.operation)
+
+ hasVariableDefaultValue := v.validDefaultValue(v.operation.VariableDefinitions[variableDefinitionRef].DefaultValue)
+ if !v.operationTypeSatisfiesDefinitionType(variableTypeRef, importedDefinitionType, hasVariableDefaultValue || hasLocationDefaultValue) {
+ v.handleVariableHasIncompatibleTypeError(value, definitionTypeRef)
+ return false
+ }
+
+ return true
+}
+
+func (v *valuesVisitor) operationTypeSatisfiesDefinitionType(operationTypeRef int, definitionTypeRef int, hasDefaultValue bool) bool {
+ opKind := v.operation.Types[operationTypeRef].TypeKind
+ defKind := v.operation.Types[definitionTypeRef].TypeKind
+
+ if opKind != ast.TypeKindNonNull && defKind == ast.TypeKindNonNull && hasDefaultValue {
+ definitionTypeRef = v.operation.Types[definitionTypeRef].OfType
+ }
+
+ for {
+ if operationTypeRef == ast.InvalidRef || definitionTypeRef == ast.InvalidRef {
+ return false
+ }
+
+ opKind = v.operation.Types[operationTypeRef].TypeKind
+ defKind = v.operation.Types[definitionTypeRef].TypeKind
+
+ if opKind == ast.TypeKindNonNull && defKind != ast.TypeKindNonNull {
+ operationTypeRef = v.operation.Types[operationTypeRef].OfType
+ continue
+ }
+
+ if opKind != defKind {
+ return false
+ }
+
+ if opKind == ast.TypeKindNamed {
+ return bytes.Equal(v.operation.TypeNameBytes(operationTypeRef), v.operation.TypeNameBytes(definitionTypeRef))
+ }
+
+ operationTypeRef = v.operation.Types[operationTypeRef].OfType
+ definitionTypeRef = v.operation.Types[definitionTypeRef].OfType
+ }
}
diff --git a/tmp/agent-patch-flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/pkg/astvalidation/operation_validation.go b/app/pkg/astvalidation/operation_validation.go
index 0057127..6293024 100644
--- a/tmp/agent-patch-flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/pkg/astvalidation/operation_validation.go
+++ b/app/pkg/astvalidation/operation_validation.go
@@ -23,7 +23,6 @@ func DefaultOperationValidator() *OperationValidator {
validator.RegisterRule(FieldSelections())
validator.RegisterRule(FieldSelectionMerging())
validator.RegisterRule(KnownArguments())
- validator.RegisterRule(ValidArguments())
validator.RegisterRule(Values())
validator.RegisterRule(ArgumentUniqueness())
validator.RegisterRule(RequiredArguments())
diff --git a/tmp/agent-patch-flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/pkg/astvalidation/operation_validation_test.go b/app/pkg/astvalidation/operation_validation_test.go
index 20c9f13..432cdd9 100644
--- a/tmp/agent-patch-flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/pkg/astvalidation/operation_validation_test.go
+++ b/app/pkg/astvalidation/operation_validation_test.go
@@ -2079,7 +2079,7 @@ func TestExecutionValidation(t *testing.T) {
doesKnowCommand(dogCommand: $catCommand)
}
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$catCommand" of type "CatCommand" used in position expecting type "DogCommand!".`))
+ Values(), Invalid, withValidationErrors(`Variable "$catCommand" of type "CatCommand" used in position expecting type "DogCommand!".`))
})
t.Run("117 variant", func(t *testing.T) {
run(t, `query argOnRequiredArg($dogCommand: CatCommand) {
@@ -2089,7 +2089,7 @@ func TestExecutionValidation(t *testing.T) {
}
}
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$dogCommand" of type "CatCommand" used in position expecting type "DogCommand!".`))
+ Values(), Invalid, withValidationErrors(`Variable "$dogCommand" of type "CatCommand" used in position expecting type "DogCommand!".`))
})
t.Run("117 variant", func(t *testing.T) {
run(t, ` query argOnRequiredArg($booleanArg: Boolean) {
@@ -2100,7 +2100,7 @@ func TestExecutionValidation(t *testing.T) {
fragment argOnOptional on Dog {
isHousetrained(atOtherHomes: $booleanArg) @include(if: true)
}`,
- ValidArguments(), Valid)
+ Values(), Valid)
})
t.Run("117 variant", func(t *testing.T) {
run(t, `
@@ -2112,7 +2112,7 @@ func TestExecutionValidation(t *testing.T) {
fragment argOnOptional on Dog {
isHousetrained(atOtherHomes: $booleanArg) @include(if: $booleanArg)
}`,
- ValidArguments(), Valid)
+ Values(), Valid)
})
t.Run("117 variant", func(t *testing.T) {
run(t, `
@@ -2124,7 +2124,7 @@ func TestExecutionValidation(t *testing.T) {
fragment argOnOptional on Dog {
isHousetrained(atOtherHomes: $booleanArg) @include(if: $booleanArg)
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$booleanArg" of type "Boolean" used in position expecting type "Boolean!".`))
+ Values(), Invalid, withValidationErrors(`Variable "$booleanArg" of type "Boolean" used in position expecting type "Boolean!".`))
})
t.Run("117 variant", func(t *testing.T) {
run(t, ` query argOnRequiredArg($booleanArg: Boolean!) {
@@ -2137,7 +2137,7 @@ func TestExecutionValidation(t *testing.T) {
isHousetrained(atOtherHomes: $booleanArg) @include(if: $booleanArg)
}
}`,
- ValidArguments(), Valid)
+ Values(), Valid)
})
t.Run("117 variant", func(t *testing.T) {
run(t, ` query argOnRequiredArg($intArg: Integer) {
@@ -2148,7 +2148,7 @@ func TestExecutionValidation(t *testing.T) {
fragment argOnOptional on Dog {
isHousetrained(atOtherHomes: $intArg) @include(if: true)
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$intArg" of type "Integer" used in position expecting type "Boolean".`))
+ Values(), Invalid, withValidationErrors(`Variable "$intArg" of type "Integer" used in position expecting type "Boolean".`))
})
t.Run("117 variant", func(t *testing.T) {
run(t, ` query argOnRequiredArg($intArg: Integer) {
@@ -2159,7 +2159,7 @@ func TestExecutionValidation(t *testing.T) {
fragment argOnOptional on Dog {
isHousetrained(atOtherHomes: $intArg) @include(if: true)
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$intArg" of type "Integer" used in position expecting type "Boolean".`))
+ Values(), Invalid, withValidationErrors(`Variable "$intArg" of type "Integer" used in position expecting type "Boolean".`))
})
t.Run("117 variant", func(t *testing.T) {
run(t, ` query argOnRequiredArg($intArg: Integer) {
@@ -2172,7 +2172,7 @@ func TestExecutionValidation(t *testing.T) {
fragment argOnOptional on Dog {
isHousetrained(atOtherHomes: $intArg) @include(if: true)
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$intArg" of type "Integer" used in position expecting type "Boolean".`))
+ Values(), Invalid, withValidationErrors(`Variable "$intArg" of type "Integer" used in position expecting type "Boolean".`))
})
t.Run("118", func(t *testing.T) {
run(t, `
@@ -2212,7 +2212,7 @@ func TestExecutionValidation(t *testing.T) {
fragment multipleArgsReverseOrder on ValidArguments {
multipleReqs(y: 2, x: 1)
}`,
- ValidArguments(), Valid)
+ Values(), Valid)
})
t.Run("undefined arg", func(t *testing.T) {
run(t, ` {
@@ -3651,7 +3651,7 @@ func TestExecutionValidation(t *testing.T) {
booleanArgField(booleanArg: $intArg)
}
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$intArg" of type "Int" used in position expecting type "Boolean".`))
+ Values(), Invalid, withValidationErrors(`Variable "$intArg" of type "Int" used in position expecting type "Boolean".`))
})
t.Run("170", func(t *testing.T) {
run(t, `query booleanListCannotGoIntoBoolean($booleanListArg: [Boolean]) {
@@ -3659,7 +3659,7 @@ func TestExecutionValidation(t *testing.T) {
booleanArgField(booleanArg: $booleanListArg)
}
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$booleanListArg" of type "[Boolean]" used in position expecting type "Boolean".`))
+ Values(), Invalid, withValidationErrors(`Variable "$booleanListArg" of type "[Boolean]" used in position expecting type "Boolean".`))
})
t.Run("171", func(t *testing.T) {
run(t, `query booleanArgQuery($booleanArg: Boolean) {
@@ -3667,7 +3667,7 @@ func TestExecutionValidation(t *testing.T) {
nonNullBooleanArgField(nonNullBooleanArg: $booleanArg)
}
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$booleanArg" of type "Boolean" used in position expecting type "Boolean!".`))
+ Values(), Invalid, withValidationErrors(`Variable "$booleanArg" of type "Boolean" used in position expecting type "Boolean!".`))
})
// Non-null types are compatible with nullable types.
t.Run("172", func(t *testing.T) {
@@ -3676,7 +3676,7 @@ func TestExecutionValidation(t *testing.T) {
nonNullListOfBooleanArgField(nonNullListOfBooleanArg: $nonNullListOfBoolean)
}
}`,
- ValidArguments(), Valid)
+ Values(), Valid)
})
t.Run("172 variant", func(t *testing.T) {
run(t, `query listToList($listOfBoolean: [Boolean]) {
@@ -3684,7 +3684,7 @@ func TestExecutionValidation(t *testing.T) {
listOfBooleanArgField(listOfBooleanArg: $listOfBoolean)
}
}`,
- ValidArguments(), Valid)
+ Values(), Valid)
})
t.Run("172 variant", func(t *testing.T) {
run(t, `query listOfNonNullToList($listOfNonNullBoolean: [Boolean!]) {
@@ -3692,7 +3692,7 @@ func TestExecutionValidation(t *testing.T) {
listOfBooleanArgField(listOfBooleanArg: $listOfNonNullBoolean)
}
}`,
- ValidArguments(), Valid)
+ Values(), Valid)
})
t.Run("172 variant", func(t *testing.T) {
run(t, `query nonNullListOfNonNullToList($nonNullListOfNonNullBoolean: [Boolean!]!) {
@@ -3700,7 +3700,7 @@ func TestExecutionValidation(t *testing.T) {
listOfBooleanArgField(listOfBooleanArg: $nonNullListOfNonNullBoolean)
}
}`,
- ValidArguments(), Valid)
+ Values(), Valid)
})
t.Run("172 variant", func(t *testing.T) {
run(t, `query nonNullListToListLiteral {
@@ -3734,7 +3734,7 @@ func TestExecutionValidation(t *testing.T) {
listOfNonNullBooleanArgField(listOfNonNullBooleanArg: $listOfBoolean)
}
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$listOfBoolean" of type "[Boolean]" used in position expecting type "[Boolean!]"`))
+ Values(), Invalid, withValidationErrors(`Variable "$listOfBoolean" of type "[Boolean]" used in position expecting type "[Boolean!]"`))
})
t.Run("172 variant", func(t *testing.T) {
run(t, `query nonNullListToListOfNonNull($nonNullListOfBoolean: [Boolean]!) {
@@ -3742,7 +3742,7 @@ func TestExecutionValidation(t *testing.T) {
listOfNonNullBooleanArgField(listOfNonNullBooleanArg: $nonNullListOfBoolean)
}
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$nonNullListOfBoolean" of type "[Boolean]!" used in position expecting type "[Boolean!]"`))
+ Values(), Invalid, withValidationErrors(`Variable "$nonNullListOfBoolean" of type "[Boolean]!" used in position expecting type "[Boolean!]"`))
})
t.Run("172 variant", func(t *testing.T) {
run(t, `query listOfNonNullToNonNullList($listOfNonNullBoolean: [Boolean!]) {
@@ -3750,7 +3750,7 @@ func TestExecutionValidation(t *testing.T) {
nonNullListOfBooleanArgField(nonNullListOfBooleanArg: $listOfNonNullBoolean)
}
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$listOfNonNullBoolean" of type "[Boolean!]" used in position expecting type "[Boolean]!"`))
+ Values(), Invalid, withValidationErrors(`Variable "$listOfNonNullBoolean" of type "[Boolean!]" used in position expecting type "[Boolean]!"`))
})
t.Run("173", func(t *testing.T) {
run(t, `query listToNonNullList($listOfBoolean: [Boolean]) {
@@ -3758,7 +3758,7 @@ func TestExecutionValidation(t *testing.T) {
nonNullListOfBooleanArgField(nonNullListOfBooleanArg: $listOfBoolean)
}
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$listOfBoolean" of type "[Boolean]" used in position expecting type "[Boolean]!"`))
+ Values(), Invalid, withValidationErrors(`Variable "$listOfBoolean" of type "[Boolean]" used in position expecting type "[Boolean]!"`))
})
t.Run("174", func(t *testing.T) {
run(t, `query booleanArgQueryWithDefault($booleanArg: Boolean) {
@@ -3766,7 +3766,7 @@ func TestExecutionValidation(t *testing.T) {
nonNullBooleanWithDefaultArgField(nonNullBooleanWithDefaultArg: $booleanArg)
}
}`,
- ValidArguments(), Valid)
+ Values(), Valid)
})
t.Run("175", func(t *testing.T) {
run(t, `query booleanArgQueryWithDefault($booleanArg: Boolean = true) {
@@ -3774,7 +3774,7 @@ func TestExecutionValidation(t *testing.T) {
nonNullBooleanArgField(nonNullBooleanArg: $booleanArg)
}
}`,
- ValidArguments(), Valid, withDisableNormalization())
+ Values(), Valid, withDisableNormalization())
})
t.Run("complex values", func(t *testing.T) {
runWithDefinition(t, wundergraphSchema, `
@@ -3789,7 +3789,7 @@ func TestExecutionValidation(t *testing.T) {
}
}
}
- `, ValidArguments(), Valid)
+ `, Values(), Valid)
})
t.Run("complex values", func(t *testing.T) {
runWithDefinition(t, wundergraphSchema, `
@@ -3870,6 +3870,36 @@ func TestExecutionValidation(t *testing.T) {
`Variable "$a" of type "Boolean" used in position expecting type "[String]"`,
))
})
+
+ t.Run("with variable on nested list field of input object", func(t *testing.T) {
+ runWithDefinition(t, `
+ scalar Boolean
+ scalar String
+
+ schema {
+ query: Query
+ }
+
+ type Query {
+ hello(arg: Input1): Boolean
+ }
+
+ input Input1 {
+ list: [Input2]
+ }
+
+ input Input2 {
+ value: String
+ }
+ `, `
+ query nestedListOfInputObject($var: Input2) {
+ hello(arg: {list: $var})
+ }
+ `, Values(), Invalid,
+ withValidationErrors(
+ `Variable "$var" of type "Input2" used in position expecting type "[Input2]"`,
+ ))
+ })
})
})
}
diff --git a/tmp/agent-patch-flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/pkg/astvalidation/reference/testsgo/harness_test.go b/app/pkg/astvalidation/reference/testsgo/harness_test.go
index 19150b0..0c409cb 100644
--- a/tmp/agent-patch-flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/pkg/astvalidation/reference/testsgo/harness_test.go
+++ b/app/pkg/astvalidation/reference/testsgo/harness_test.go
@@ -86,7 +86,7 @@ var rulesMap = map[string][]astvalidation.Rule{
ValuesOfCorrectTypeRule: {astvalidation.Values()},
VariablesAreInputTypesRule: {astvalidation.VariablesAreInputTypes()},
KnownTypeNamesOperationRule: {astvalidation.VariablesAreInputTypes(), astvalidation.Fragments()},
- VariablesInAllowedPositionRule: {astvalidation.ValidArguments(), astvalidation.Values()},
+ VariablesInAllowedPositionRule: {astvalidation.Values()},
// fragments rules
FragmentsOnCompositeTypesRule: {astvalidation.Fragments()},
diff --git a/tmp/agent-patch-flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/astvalidation/operation_rule_valid_arguments.go b/app/v2/pkg/astvalidation/operation_rule_valid_arguments.go
index 0608211..ea1debb 100644
--- a/tmp/agent-patch-flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/astvalidation/operation_rule_valid_arguments.go
+++ b/app/v2/pkg/astvalidation/operation_rule_valid_arguments.go
@@ -1,184 +1,9 @@
package astvalidation
-import (
- "bytes"
- "fmt"
+import "github.com/wundergraph/graphql-go-tools/v2/pkg/astvisitor"
- "github.com/wundergraph/graphql-go-tools/v2/pkg/ast"
- "github.com/wundergraph/graphql-go-tools/v2/pkg/astvisitor"
- "github.com/wundergraph/graphql-go-tools/v2/pkg/operationreport"
-)
-
-// ValidArguments validates if arguments are valid: values and variables has compatible types
-// deep variables comparison is handled by Values
+// ValidArguments is deprecated.
+// Variable argument type checks are validated by Values().
func ValidArguments() Rule {
- return func(walker *astvisitor.Walker) {
- visitor := validArgumentsVisitor{
- Walker: walker,
- }
- walker.RegisterEnterDocumentVisitor(&visitor)
- walker.RegisterEnterArgumentVisitor(&visitor)
- }
-}
-
-type validArgumentsVisitor struct {
- *astvisitor.Walker
- operation, definition *ast.Document
-}
-
-func (v *validArgumentsVisitor) EnterDocument(operation, definition *ast.Document) {
- v.operation = operation
- v.definition = definition
-}
-
-func (v *validArgumentsVisitor) EnterArgument(ref int) {
- definitionRef, exists := v.ArgumentInputValueDefinition(ref)
-
- if !exists {
- return
- }
-
- value := v.operation.ArgumentValue(ref)
- v.validateIfValueSatisfiesInputFieldDefinition(value, definitionRef)
-}
-
-func (v *validArgumentsVisitor) validateIfValueSatisfiesInputFieldDefinition(value ast.Value, inputValueDefinitionRef int) {
- var (
- satisfied bool
- operationTypeRef int
- variableDefinitionRef int
- )
-
- switch value.Kind {
- case ast.ValueKindVariable:
- satisfied, operationTypeRef, variableDefinitionRef = v.variableValueSatisfiesInputValueDefinition(value.Ref, inputValueDefinitionRef)
- case ast.ValueKindEnum,
- ast.ValueKindNull,
- ast.ValueKindBoolean,
- ast.ValueKindInteger,
- ast.ValueKindString,
- ast.ValueKindFloat,
- ast.ValueKindObject,
- ast.ValueKindList:
- // this types of values are covered by Values() / valuesVisitor
- return
- default:
- v.StopWithInternalErr(fmt.Errorf("validateIfValueSatisfiesInputFieldDefinition: not implemented for value.Kind: %s", value.Kind))
- return
- }
-
- if satisfied {
- return
- }
-
- if operationTypeRef == ast.InvalidRef {
- // variable is not defined
- return
- }
-
- printedValue, err := v.operation.PrintValueBytes(value, nil)
- if v.HandleInternalErr(err) {
- return
- }
-
- typeRef := v.definition.InputValueDefinitionType(inputValueDefinitionRef)
- expectedTypeName, err := v.definition.PrintTypeBytes(typeRef, nil)
- if v.HandleInternalErr(err) {
- return
- }
-
- actualTypeName, err := v.operation.PrintTypeBytes(operationTypeRef, nil)
- if v.HandleInternalErr(err) {
- return
- }
-
- v.StopWithExternalErr(operationreport.ErrVariableTypeDoesntSatisfyInputValueDefinition(printedValue, actualTypeName, expectedTypeName, value.Position, v.operation.VariableDefinitions[variableDefinitionRef].VariableValue.Position))
-}
-
-func (v *validArgumentsVisitor) variableValueSatisfiesInputValueDefinition(variableValue, inputValueDefinition int) (satisfies bool, operationTypeRef int, variableDefRef int) {
- variableDefinitionRef, exists := v.variableDefinition(variableValue)
- if !exists {
- return false, ast.InvalidRef, variableDefinitionRef
- }
-
- operationTypeRef = v.operation.VariableDefinitions[variableDefinitionRef].Type
- definitionTypeRef := v.definition.InputValueDefinitions[inputValueDefinition].Type
-
- hasDefaultValue := v.validDefaultValue(v.operation.VariableDefinitions[variableDefinitionRef].DefaultValue) ||
- v.validDefaultValue(v.definition.InputValueDefinitions[inputValueDefinition].DefaultValue)
-
- return v.operationTypeSatisfiesDefinitionType(operationTypeRef, definitionTypeRef, hasDefaultValue), operationTypeRef, variableDefinitionRef
-}
-
-func (v *validArgumentsVisitor) variableDefinition(variableValueRef int) (ref int, exists bool) {
- variableName := v.operation.VariableValueNameBytes(variableValueRef)
-
- if v.Ancestors[0].Kind == ast.NodeKindOperationDefinition {
- return v.operation.VariableDefinitionByNameAndOperation(v.Ancestors[0].Ref, variableName)
- }
-
- for opDefRef := 0; opDefRef < len(v.operation.OperationDefinitions); opDefRef++ {
- ref, exists = v.operation.VariableDefinitionByNameAndOperation(opDefRef, variableName)
- if exists {
- return
- }
- }
-
- return ast.InvalidRef, false
-}
-
-func (v *validArgumentsVisitor) validDefaultValue(value ast.DefaultValue) bool {
- return value.IsDefined && value.Value.Kind != ast.ValueKindNull
-}
-
-func (v *validArgumentsVisitor) operationTypeSatisfiesDefinitionType(operationTypeRef int, definitionTypeRef int, hasDefaultValue bool) bool {
- opKind := v.operation.Types[operationTypeRef].TypeKind
- defKind := v.definition.Types[definitionTypeRef].TypeKind
-
- // A nullable op type is compatible with a non-null def type if the def has
- // a default value. Strip the def non-null and continue comparing. This
- // logic is only valid before any unnesting of types occurs, which is why
- // it's outside the for loop below.
- //
- // Example:
- // Op: someField(arg: Boolean): String
- // Def: someField(arg: Boolean! = false): String # Boolean! -> Boolean
- if opKind != ast.TypeKindNonNull && defKind == ast.TypeKindNonNull && hasDefaultValue {
- definitionTypeRef = v.definition.Types[definitionTypeRef].OfType
- }
-
- // Unnest the op and def arg types until a named type is reached,
- // then compare.
- for {
- if operationTypeRef == -1 || definitionTypeRef == -1 {
- return false
- }
- opKind = v.operation.Types[operationTypeRef].TypeKind
- defKind = v.definition.Types[definitionTypeRef].TypeKind
-
- // If the op arg type is stricter than the def arg type, that's okay.
- // Strip the op non-null and continue comparing.
- //
- // Example:
- // Op: someField(arg: Boolean!): String # Boolean! -> Boolean
- // Def: someField(arg: Boolean): String
- if opKind == ast.TypeKindNonNull && defKind != ast.TypeKindNonNull {
- operationTypeRef = v.operation.Types[operationTypeRef].OfType
- continue
- }
-
- if opKind != defKind {
- return false
- }
- if opKind == ast.TypeKindNamed {
- // defKind is also a named type because at this point both kinds
- // are the same! Compare the names.
-
- return bytes.Equal(v.operation.Input.ByteSlice(v.operation.Types[operationTypeRef].Name),
- v.definition.Input.ByteSlice(v.definition.Types[definitionTypeRef].Name))
- }
- // Both types are non-null or list. Unnest and continue comparing.
- operationTypeRef = v.operation.Types[operationTypeRef].OfType
- definitionTypeRef = v.definition.Types[definitionTypeRef].OfType
- }
+ return func(walker *astvisitor.Walker) {}
}
diff --git a/tmp/agent-patch-flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/astvalidation/operation_rule_values.go b/app/v2/pkg/astvalidation/operation_rule_values.go
index 3b6d7b5..a1e132d 100644
--- a/tmp/agent-patch-flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/astvalidation/operation_rule_values.go
+++ b/app/v2/pkg/astvalidation/operation_rule_values.go
@@ -45,27 +45,13 @@ func (v *valuesVisitor) EnterVariableDefinition(ref int) {
func (v *valuesVisitor) EnterArgument(ref int) {
- definition, exists := v.ArgumentInputValueDefinition(ref)
+ inputValueDefinitionRef, exists := v.ArgumentInputValueDefinition(ref)
if !exists {
return
}
value := v.operation.ArgumentValue(ref)
- if value.Kind == ast.ValueKindVariable {
- variableName := v.operation.VariableValueNameBytes(value.Ref)
- variableDefinition, exists := v.operation.VariableDefinitionByNameAndOperation(v.Ancestors[0].Ref, variableName)
- if !exists {
- operationName := v.operation.OperationDefinitionNameBytes(v.Ancestors[0].Ref)
- v.StopWithExternalErr(operationreport.ErrVariableNotDefinedOnOperation(variableName, operationName))
- return
- }
- if !v.operation.VariableDefinitions[variableDefinition].DefaultValue.IsDefined {
- return // variable has no default value, deep type check not required
- }
- value = v.operation.VariableDefinitions[variableDefinition].DefaultValue.Value
- }
-
- v.valueSatisfiesInputValueDefinitionType(value, v.definition.InputValueDefinitions[definition].Type)
+ v.valueSatisfiesInputValueDefinition(value, inputValueDefinitionRef)
}
func (v *valuesVisitor) valueSatisfiesOperationType(value ast.Value, operationTypeRef int) bool {
@@ -153,7 +139,19 @@ func (v *valuesVisitor) valueSatisfiesOperationListType(value ast.Value, operati
return valid
}
-func (v *valuesVisitor) valueSatisfiesInputValueDefinitionType(value ast.Value, definitionTypeRef int) bool {
+func (v *valuesVisitor) valueSatisfiesInputValueDefinition(value ast.Value, inputValueDefinitionRef int) bool {
+ return v.valueSatisfiesInputValueDefinitionType(
+ value,
+ v.definition.InputValueDefinitions[inputValueDefinitionRef].Type,
+ v.validDefaultValue(v.definition.InputValueDefinitions[inputValueDefinitionRef].DefaultValue),
+ )
+}
+
+func (v *valuesVisitor) valueSatisfiesInputValueDefinitionType(value ast.Value, definitionTypeRef int, hasLocationDefaultValue bool) bool {
+ if value.Kind == ast.ValueKindVariable {
+ return v.variableValueSatisfiesInputValueDefinitionType(value, definitionTypeRef, hasLocationDefaultValue)
+ }
+
switch v.definition.Types[definitionTypeRef].TypeKind {
case ast.TypeKindNonNull:
return v.valuesSatisfiesNonNullType(value, definitionTypeRef)
@@ -168,29 +166,11 @@ func (v *valuesVisitor) valueSatisfiesInputValueDefinitionType(value ast.Value,
}
func (v *valuesVisitor) valuesSatisfiesNonNullType(value ast.Value, definitionTypeRef int) bool {
- switch value.Kind {
- case ast.ValueKindNull:
+ if value.Kind == ast.ValueKindNull {
v.handleUnexpectedNullError(value, definitionTypeRef)
return false
- case ast.ValueKindVariable:
- variableDefinitionRef, variableTypeRef, _, ok := v.operationVariableType(value.Ref)
- if !ok {
- v.handleTypeError(value, definitionTypeRef)
- return false
- }
-
- if v.operation.VariableDefinitionHasDefaultValue(variableDefinitionRef) {
- return v.valueSatisfiesInputValueDefinitionType(v.operation.VariableDefinitions[variableDefinitionRef].DefaultValue.Value, definitionTypeRef)
- }
-
- importedDefinitionType := v.importer.ImportType(definitionTypeRef, v.definition, v.operation)
- if !v.operation.TypesAreEqualDeep(importedDefinitionType, variableTypeRef) {
- v.handleVariableHasIncompatibleTypeError(value, definitionTypeRef)
- return false
- }
- return true
}
- return v.valueSatisfiesInputValueDefinitionType(value, v.definition.Types[definitionTypeRef].OfType)
+ return v.valueSatisfiesInputValueDefinitionType(value, v.definition.Types[definitionTypeRef].OfType, false)
}
func (v *valuesVisitor) valuesSatisfiesNamedType(value ast.Value, definitionTypeRef int) bool {
@@ -210,34 +190,12 @@ func (v *valuesVisitor) valuesSatisfiesNamedType(value ast.Value, definitionType
}
func (v *valuesVisitor) valueSatisfiesListType(value ast.Value, definitionTypeRef int, listItemType int) bool {
-
- if value.Kind == ast.ValueKindVariable {
- variableDefinitionRef, actualType, _, ok := v.operationVariableType(value.Ref)
- if !ok {
- v.handleTypeError(value, definitionTypeRef)
- return false
- }
-
- if v.operation.VariableDefinitionHasDefaultValue(variableDefinitionRef) {
- return v.valueSatisfiesInputValueDefinitionType(v.operation.VariableDefinitions[variableDefinitionRef].DefaultValue.Value, definitionTypeRef)
- }
-
- expectedType := v.importer.ImportType(listItemType, v.definition, v.operation)
- actualType = v.operation.ResolveUnderlyingType(actualType)
-
- if !v.operation.TypesAreEqualDeep(expectedType, actualType) {
- v.handleVariableHasIncompatibleTypeError(value, definitionTypeRef)
- return false
- }
- return true
- }
-
if value.Kind == ast.ValueKindNull {
return true
}
if value.Kind != ast.ValueKindList {
- return v.valueSatisfiesInputValueDefinitionType(value, listItemType)
+ return v.valueSatisfiesInputValueDefinitionType(value, listItemType, false)
}
if v.definition.Types[listItemType].TypeKind == ast.TypeKindNonNull {
@@ -252,7 +210,7 @@ func (v *valuesVisitor) valueSatisfiesListType(value ast.Value, definitionTypeRe
for _, i := range v.operation.ListValues[value.Ref].Refs {
listValue := v.operation.Value(i)
- if !v.valueSatisfiesInputValueDefinitionType(listValue, listItemType) {
+ if !v.valueSatisfiesInputValueDefinitionType(listValue, listItemType, false) {
valid = false
}
}
@@ -273,11 +231,6 @@ func (v *valuesVisitor) valueSatisfiesTypeDefinitionNode(value ast.Value, defini
}
func (v *valuesVisitor) valueSatisfiesEnum(value ast.Value, definitionTypeRef int, node ast.Node) bool {
- if value.Kind == ast.ValueKindVariable {
- expectedTypeName := node.NameBytes(v.definition)
- return v.variableValueHasMatchingTypeName(value, definitionTypeRef, expectedTypeName)
- }
-
if value.Kind != ast.ValueKindEnum {
v.handleUnexpectedEnumValueError(value, definitionTypeRef)
return false
@@ -296,10 +249,6 @@ func (v *valuesVisitor) valueSatisfiesEnum(value ast.Value, definitionTypeRef in
func (v *valuesVisitor) valueSatisfiesScalar(value ast.Value, definitionTypeRef int, scalar int) bool {
scalarName := v.definition.ScalarTypeDefinitionNameBytes(scalar)
- if value.Kind == ast.ValueKindVariable {
- return v.variableValueHasMatchingTypeName(value, definitionTypeRef, scalarName)
- }
-
switch {
case bytes.Equal(scalarName, literal.ID):
return v.valueSatisfiesScalarID(value, definitionTypeRef)
@@ -407,11 +356,6 @@ func (v *valuesVisitor) valueSatisfiesScalarString(value ast.Value, definitionTy
}
func (v *valuesVisitor) valueSatisfiesInputObjectTypeDefinition(value ast.Value, definitionTypeRef int, inputObjectTypeDefinition int) bool {
- if value.Kind == ast.ValueKindVariable {
- expectedTypeName := v.definition.InputObjectTypeDefinitionNameBytes(inputObjectTypeDefinition)
- return v.variableValueHasMatchingTypeName(value, definitionTypeRef, expectedTypeName)
- }
-
if value.Kind != ast.ValueKindObject {
v.handleNotObjectTypeError(value, definitionTypeRef)
return false
@@ -494,12 +438,11 @@ func (v *valuesVisitor) objectFieldDefined(objectField, inputObjectTypeDefinitio
func (v *valuesVisitor) objectValueSatisfiesInputValueDefinition(objectValue ast.Value, inputObjectDefinition, inputValueDefinition int) bool {
name := v.definition.InputValueDefinitionNameBytes(inputValueDefinition)
- definitionTypeRef := v.definition.InputValueDefinitionType(inputValueDefinition)
for _, i := range v.operation.ObjectValues[objectValue.Ref].Refs {
if bytes.Equal(name, v.operation.ObjectFieldNameBytes(i)) {
value := v.operation.ObjectFieldValue(i)
- return v.valueSatisfiesInputValueDefinitionType(value, definitionTypeRef)
+ return v.valueSatisfiesInputValueDefinition(value, inputValueDefinition)
}
}
@@ -512,25 +455,6 @@ func (v *valuesVisitor) objectValueSatisfiesInputValueDefinition(objectValue ast
return true
}
-func (v *valuesVisitor) variableValueHasMatchingTypeName(value ast.Value, definitionTypeRef int, expectedTypeName []byte) bool {
- variableDefinitionRef, _, actualTypeName, ok := v.operationVariableType(value.Ref)
- if !ok {
- v.handleVariableHasIncompatibleTypeError(value, definitionTypeRef)
- return false
- }
-
- if v.operation.VariableDefinitionHasDefaultValue(variableDefinitionRef) {
- return v.valueSatisfiesInputValueDefinitionType(v.operation.VariableDefinitions[variableDefinitionRef].DefaultValue.Value, definitionTypeRef)
- }
-
- if !bytes.Equal(actualTypeName, expectedTypeName) {
- v.handleVariableHasIncompatibleTypeError(value, definitionTypeRef)
- return false
- }
-
- return true
-}
-
func (v *valuesVisitor) handleTypeError(value ast.Value, definitionTypeRef int) {
printedValue, printedType, ok := v.printValueAndUnderlyingType(value, definitionTypeRef)
if !ok {
@@ -587,11 +511,16 @@ func (v *valuesVisitor) handleVariableHasIncompatibleTypeError(value ast.Value,
return
}
- variableDefinitionRef, _, actualTypeName, ok := v.operationVariableType(value.Ref)
+ variableDefinitionRef, variableTypeRef, ok := v.operationVariableType(value.Ref)
if !ok {
return
}
+ actualTypeName, err := v.operation.PrintTypeBytes(variableTypeRef, nil)
+ if v.HandleInternalErr(err) {
+ return
+ }
+
v.Report.AddExternalError(operationreport.ErrVariableTypeDoesntSatisfyInputValueDefinition(
printedValue,
actualTypeName,
@@ -703,14 +632,71 @@ func (v *valuesVisitor) operationVariableDefinition(variableValueRef int) (ref i
return ast.InvalidRef, false
}
-func (v *valuesVisitor) operationVariableType(variableValueRef int) (variableDefinitionRef int, variableTypeRef int, typeName ast.ByteSlice, ok bool) {
+func (v *valuesVisitor) operationVariableType(variableValueRef int) (variableDefinitionRef int, variableTypeRef int, ok bool) {
variableDefRef, exists := v.operationVariableDefinition(variableValueRef)
if !exists {
- return ast.InvalidRef, ast.InvalidRef, nil, false
+ return ast.InvalidRef, ast.InvalidRef, false
}
variableTypeRef = v.operation.VariableDefinitions[variableDefRef].Type
- typeName = v.operation.ResolveTypeNameBytes(variableTypeRef)
- return variableDefRef, variableTypeRef, typeName, true
+ return variableDefRef, variableTypeRef, true
+}
+
+func (v *valuesVisitor) validDefaultValue(value ast.DefaultValue) bool {
+ return value.IsDefined && value.Value.Kind != ast.ValueKindNull
+}
+
+func (v *valuesVisitor) variableValueSatisfiesInputValueDefinitionType(value ast.Value, definitionTypeRef int, hasLocationDefaultValue bool) bool {
+ variableDefinitionRef, variableTypeRef, ok := v.operationVariableType(value.Ref)
+ if !ok {
+ variableName := v.operation.VariableValueNameBytes(value.Ref)
+ operationName := v.operation.OperationDefinitionNameBytes(v.Ancestors[0].Ref)
+ v.StopWithExternalErr(operationreport.ErrVariableNotDefinedOnOperation(variableName, operationName))
+ return false
+ }
+
+ importedDefinitionType := v.importer.ImportType(definitionTypeRef, v.definition, v.operation)
+
+ hasVariableDefaultValue := v.validDefaultValue(v.operation.VariableDefinitions[variableDefinitionRef].DefaultValue)
+ if !v.operationTypeSatisfiesDefinitionType(variableTypeRef, importedDefinitionType, hasVariableDefaultValue || hasLocationDefaultValue) {
+ v.handleVariableHasIncompatibleTypeError(value, definitionTypeRef)
+ return false
+ }
+
+ return true
+}
+
+func (v *valuesVisitor) operationTypeSatisfiesDefinitionType(operationTypeRef int, definitionTypeRef int, hasDefaultValue bool) bool {
+ opKind := v.operation.Types[operationTypeRef].TypeKind
+ defKind := v.operation.Types[definitionTypeRef].TypeKind
+
+ if opKind != ast.TypeKindNonNull && defKind == ast.TypeKindNonNull && hasDefaultValue {
+ definitionTypeRef = v.operation.Types[definitionTypeRef].OfType
+ }
+
+ for {
+ if operationTypeRef == ast.InvalidRef || definitionTypeRef == ast.InvalidRef {
+ return false
+ }
+
+ opKind = v.operation.Types[operationTypeRef].TypeKind
+ defKind = v.operation.Types[definitionTypeRef].TypeKind
+
+ if opKind == ast.TypeKindNonNull && defKind != ast.TypeKindNonNull {
+ operationTypeRef = v.operation.Types[operationTypeRef].OfType
+ continue
+ }
+
+ if opKind != defKind {
+ return false
+ }
+
+ if opKind == ast.TypeKindNamed {
+ return bytes.Equal(v.operation.TypeNameBytes(operationTypeRef), v.operation.TypeNameBytes(definitionTypeRef))
+ }
+
+ operationTypeRef = v.operation.Types[operationTypeRef].OfType
+ definitionTypeRef = v.operation.Types[definitionTypeRef].OfType
+ }
}
diff --git a/tmp/agent-patch-flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/astvalidation/operation_validation.go b/app/v2/pkg/astvalidation/operation_validation.go
index fa1546c..b33c80b 100644
--- a/tmp/agent-patch-flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/astvalidation/operation_validation.go
+++ b/app/v2/pkg/astvalidation/operation_validation.go
@@ -39,7 +39,6 @@ func DefaultOperationValidator(options ...Option) *OperationValidator {
validator.RegisterRule(FieldSelections(opts))
validator.RegisterRule(FieldSelectionMerging())
validator.RegisterRule(KnownArguments())
- validator.RegisterRule(ValidArguments())
validator.RegisterRule(Values())
validator.RegisterRule(ArgumentUniqueness())
validator.RegisterRule(RequiredArguments())
diff --git a/tmp/agent-patch-flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/astvalidation/operation_validation_test.go b/app/v2/pkg/astvalidation/operation_validation_test.go
index 821f6a6..3fe2dbe 100644
--- a/tmp/agent-patch-flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/astvalidation/operation_validation_test.go
+++ b/app/v2/pkg/astvalidation/operation_validation_test.go
@@ -2118,7 +2118,7 @@ func TestExecutionValidation(t *testing.T) {
doesKnowCommand(dogCommand: $catCommand)
}
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$catCommand" of type "CatCommand" used in position expecting type "DogCommand!".`))
+ Values(), Invalid, withValidationErrors(`Variable "$catCommand" of type "CatCommand" used in position expecting type "DogCommand!".`))
})
t.Run("117 variant", func(t *testing.T) {
run(t, `query argOnRequiredArg($dogCommand: CatCommand) {
@@ -2128,7 +2128,7 @@ func TestExecutionValidation(t *testing.T) {
}
}
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$dogCommand" of type "CatCommand" used in position expecting type "DogCommand!".`))
+ Values(), Invalid, withValidationErrors(`Variable "$dogCommand" of type "CatCommand" used in position expecting type "DogCommand!".`))
})
t.Run("117 variant", func(t *testing.T) {
run(t, ` query argOnRequiredArg($booleanArg: Boolean) {
@@ -2139,7 +2139,7 @@ func TestExecutionValidation(t *testing.T) {
fragment argOnOptional on Dog {
isHousetrained(atOtherHomes: $booleanArg) @include(if: true)
}`,
- ValidArguments(), Valid)
+ Values(), Valid)
})
t.Run("117 variant", func(t *testing.T) {
run(t, `
@@ -2151,7 +2151,7 @@ func TestExecutionValidation(t *testing.T) {
fragment argOnOptional on Dog {
isHousetrained(atOtherHomes: $booleanArg) @include(if: $booleanArg)
}`,
- ValidArguments(), Valid)
+ Values(), Valid)
})
t.Run("117 variant", func(t *testing.T) {
run(t, `
@@ -2163,7 +2163,7 @@ func TestExecutionValidation(t *testing.T) {
fragment argOnOptional on Dog {
isHousetrained(atOtherHomes: $booleanArg) @include(if: $booleanArg)
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$booleanArg" of type "Boolean" used in position expecting type "Boolean!".`))
+ Values(), Invalid, withValidationErrors(`Variable "$booleanArg" of type "Boolean" used in position expecting type "Boolean!".`))
})
t.Run("117 variant", func(t *testing.T) {
run(t, ` query argOnRequiredArg($booleanArg: Boolean!) {
@@ -2176,7 +2176,7 @@ func TestExecutionValidation(t *testing.T) {
isHousetrained(atOtherHomes: $booleanArg) @include(if: $booleanArg)
}
}`,
- ValidArguments(), Valid)
+ Values(), Valid)
})
t.Run("117 variant", func(t *testing.T) {
run(t, ` query argOnRequiredArg($intArg: Integer) {
@@ -2187,7 +2187,7 @@ func TestExecutionValidation(t *testing.T) {
fragment argOnOptional on Dog {
isHousetrained(atOtherHomes: $intArg) @include(if: true)
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$intArg" of type "Integer" used in position expecting type "Boolean".`))
+ Values(), Invalid, withValidationErrors(`Variable "$intArg" of type "Integer" used in position expecting type "Boolean".`))
})
t.Run("117 variant", func(t *testing.T) {
run(t, ` query argOnRequiredArg($intArg: Integer) {
@@ -2198,7 +2198,7 @@ func TestExecutionValidation(t *testing.T) {
fragment argOnOptional on Dog {
isHousetrained(atOtherHomes: $intArg) @include(if: true)
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$intArg" of type "Integer" used in position expecting type "Boolean".`))
+ Values(), Invalid, withValidationErrors(`Variable "$intArg" of type "Integer" used in position expecting type "Boolean".`))
})
t.Run("117 variant", func(t *testing.T) {
run(t, ` query argOnRequiredArg($intArg: Integer) {
@@ -2211,7 +2211,7 @@ func TestExecutionValidation(t *testing.T) {
fragment argOnOptional on Dog {
isHousetrained(atOtherHomes: $intArg) @include(if: true)
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$intArg" of type "Integer" used in position expecting type "Boolean".`))
+ Values(), Invalid, withValidationErrors(`Variable "$intArg" of type "Integer" used in position expecting type "Boolean".`))
})
t.Run("118", func(t *testing.T) {
run(t, `
@@ -2251,7 +2251,7 @@ func TestExecutionValidation(t *testing.T) {
fragment multipleArgsReverseOrder on ValidArguments {
multipleReqs(y: 2, x: 1)
}`,
- ValidArguments(), Valid)
+ Values(), Valid)
})
t.Run("undefined arg", func(t *testing.T) {
run(t, ` {
@@ -3729,7 +3729,7 @@ func TestExecutionValidation(t *testing.T) {
booleanArgField(booleanArg: $intArg)
}
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$intArg" of type "Int" used in position expecting type "Boolean".`))
+ Values(), Invalid, withValidationErrors(`Variable "$intArg" of type "Int" used in position expecting type "Boolean".`))
})
t.Run("170", func(t *testing.T) {
run(t, `query booleanListCannotGoIntoBoolean($booleanListArg: [Boolean]) {
@@ -3737,7 +3737,7 @@ func TestExecutionValidation(t *testing.T) {
booleanArgField(booleanArg: $booleanListArg)
}
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$booleanListArg" of type "[Boolean]" used in position expecting type "Boolean".`))
+ Values(), Invalid, withValidationErrors(`Variable "$booleanListArg" of type "[Boolean]" used in position expecting type "Boolean".`))
})
t.Run("171", func(t *testing.T) {
run(t, `query booleanArgQuery($booleanArg: Boolean) {
@@ -3745,7 +3745,7 @@ func TestExecutionValidation(t *testing.T) {
nonNullBooleanArgField(nonNullBooleanArg: $booleanArg)
}
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$booleanArg" of type "Boolean" used in position expecting type "Boolean!".`))
+ Values(), Invalid, withValidationErrors(`Variable "$booleanArg" of type "Boolean" used in position expecting type "Boolean!".`))
})
// Non-null types are compatible with nullable types.
t.Run("172", func(t *testing.T) {
@@ -3754,7 +3754,7 @@ func TestExecutionValidation(t *testing.T) {
nonNullListOfBooleanArgField(nonNullListOfBooleanArg: $nonNullListOfBoolean)
}
}`,
- ValidArguments(), Valid)
+ Values(), Valid)
})
t.Run("172 variant", func(t *testing.T) {
run(t, `query listToList($listOfBoolean: [Boolean]) {
@@ -3762,7 +3762,7 @@ func TestExecutionValidation(t *testing.T) {
listOfBooleanArgField(listOfBooleanArg: $listOfBoolean)
}
}`,
- ValidArguments(), Valid)
+ Values(), Valid)
})
t.Run("172 variant", func(t *testing.T) {
run(t, `query listOfNonNullToList($listOfNonNullBoolean: [Boolean!]) {
@@ -3770,7 +3770,7 @@ func TestExecutionValidation(t *testing.T) {
listOfBooleanArgField(listOfBooleanArg: $listOfNonNullBoolean)
}
}`,
- ValidArguments(), Valid)
+ Values(), Valid)
})
t.Run("172 variant", func(t *testing.T) {
run(t, `query nonNullListOfNonNullToList($nonNullListOfNonNullBoolean: [Boolean!]!) {
@@ -3778,7 +3778,7 @@ func TestExecutionValidation(t *testing.T) {
listOfBooleanArgField(listOfBooleanArg: $nonNullListOfNonNullBoolean)
}
}`,
- ValidArguments(), Valid)
+ Values(), Valid)
})
t.Run("172 variant", func(t *testing.T) {
run(t, `query nonNullListToListLiteral {
@@ -3812,7 +3812,7 @@ func TestExecutionValidation(t *testing.T) {
listOfNonNullBooleanArgField(listOfNonNullBooleanArg: $listOfBoolean)
}
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$listOfBoolean" of type "[Boolean]" used in position expecting type "[Boolean!]"`))
+ Values(), Invalid, withValidationErrors(`Variable "$listOfBoolean" of type "[Boolean]" used in position expecting type "[Boolean!]"`))
})
t.Run("172 variant", func(t *testing.T) {
run(t, `query nonNullListToListOfNonNull($nonNullListOfBoolean: [Boolean]!) {
@@ -3820,7 +3820,7 @@ func TestExecutionValidation(t *testing.T) {
listOfNonNullBooleanArgField(listOfNonNullBooleanArg: $nonNullListOfBoolean)
}
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$nonNullListOfBoolean" of type "[Boolean]!" used in position expecting type "[Boolean!]"`))
+ Values(), Invalid, withValidationErrors(`Variable "$nonNullListOfBoolean" of type "[Boolean]!" used in position expecting type "[Boolean!]"`))
})
t.Run("172 variant", func(t *testing.T) {
run(t, `query listOfNonNullToNonNullList($listOfNonNullBoolean: [Boolean!]) {
@@ -3828,7 +3828,7 @@ func TestExecutionValidation(t *testing.T) {
nonNullListOfBooleanArgField(nonNullListOfBooleanArg: $listOfNonNullBoolean)
}
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$listOfNonNullBoolean" of type "[Boolean!]" used in position expecting type "[Boolean]!"`))
+ Values(), Invalid, withValidationErrors(`Variable "$listOfNonNullBoolean" of type "[Boolean!]" used in position expecting type "[Boolean]!"`))
})
t.Run("173", func(t *testing.T) {
run(t, `query listToNonNullList($listOfBoolean: [Boolean]) {
@@ -3836,7 +3836,7 @@ func TestExecutionValidation(t *testing.T) {
nonNullListOfBooleanArgField(nonNullListOfBooleanArg: $listOfBoolean)
}
}`,
- ValidArguments(), Invalid, withValidationErrors(`Variable "$listOfBoolean" of type "[Boolean]" used in position expecting type "[Boolean]!"`))
+ Values(), Invalid, withValidationErrors(`Variable "$listOfBoolean" of type "[Boolean]" used in position expecting type "[Boolean]!"`))
})
t.Run("174", func(t *testing.T) {
run(t, `query booleanArgQueryWithDefault($booleanArg: Boolean) {
@@ -3844,7 +3844,7 @@ func TestExecutionValidation(t *testing.T) {
nonNullBooleanWithDefaultArgField(nonNullBooleanWithDefaultArg: $booleanArg)
}
}`,
- ValidArguments(), Valid)
+ Values(), Valid)
})
t.Run("175", func(t *testing.T) {
run(t, `query booleanArgQueryWithDefault($booleanArg: Boolean = true) {
@@ -3852,7 +3852,7 @@ func TestExecutionValidation(t *testing.T) {
nonNullBooleanArgField(nonNullBooleanArg: $booleanArg)
}
}`,
- ValidArguments(), Valid, withDisableNormalization())
+ Values(), Valid, withDisableNormalization())
})
t.Run("complex values", func(t *testing.T) {
runWithDefinition(t, wundergraphSchema, `
@@ -3867,7 +3867,7 @@ func TestExecutionValidation(t *testing.T) {
}
}
}
- `, ValidArguments(), Valid)
+ `, Values(), Valid)
})
t.Run("complex values", func(t *testing.T) {
runWithDefinition(t, wundergraphSchema, `
@@ -3949,6 +3949,36 @@ func TestExecutionValidation(t *testing.T) {
))
})
+ t.Run("with variable on nested list field of input object", func(t *testing.T) {
+ runWithDefinition(t, `
+ scalar Boolean
+ scalar String
+
+ schema {
+ query: Query
+ }
+
+ type Query {
+ hello(arg: Input1): Boolean
+ }
+
+ input Input1 {
+ list: [Input2]
+ }
+
+ input Input2 {
+ value: String
+ }
+ `, `
+ query nestedListOfInputObject($var: Input2) {
+ hello(arg: {list: $var})
+ }
+ `, Values(), Invalid,
+ withValidationErrors(
+ `Variable "$var" of type "Input2" used in position expecting type "[Input2]"`,
+ ))
+ })
+
t.Run("complex nested optionalListOfOptionalStrings of type [String] should accept more restrictive type [String!]!", func(t *testing.T) {
runWithDefinition(t, `
scalar String
diff --git a/tmp/agent-patch-flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/astvalidation/reference/testsgo/harness_test.go b/app/v2/pkg/astvalidation/reference/testsgo/harness_test.go
index 00566f0..6f18dbf 100644
--- a/tmp/agent-patch-flux-pr-1099.1-of-1.2026-02-28__13-38-10__gpt-5-3-codex/app/v2/pkg/astvalidation/reference/testsgo/harness_test.go
+++ b/app/v2/pkg/astvalidation/reference/testsgo/harness_test.go
@@ -86,7 +86,7 @@ var rulesMap = map[string][]astvalidation.Rule{
ValuesOfCorrectTypeRule: {astvalidation.Values()},
VariablesAreInputTypesRule: {astvalidation.VariablesAreInputTypes()},
KnownTypeNamesOperationRule: {astvalidation.VariablesAreInputTypes(), astvalidation.Fragments()},
- VariablesInAllowedPositionRule: {astvalidation.ValidArguments(), astvalidation.Values()},
+ VariablesInAllowedPositionRule: {astvalidation.Values()},
// fragments rules
FragmentsOnCompositeTypesRule: {astvalidation.Fragments()},