STET

agent_patch

runs/2026-02-28__13-38-10__gpt-5-4/flux-pr-1308/flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/agent-logs/agent.patch

29866 bytes

Back to adjudication
diff --git a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/asttransform/baseschema.go b/app/v2/pkg/asttransform/baseschema.go
index 45a6ebc..7450991 100644
--- a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/asttransform/baseschema.go
+++ b/app/v2/pkg/asttransform/baseschema.go
@@ -168,6 +168,9 @@ directive @deprecated(
 
 directive @specifiedBy(url: String!) on SCALAR
 
+"Requires exactly one field to be supplied and that field must not be null."
+directive @oneOf on INPUT_OBJECT
+
 """
 A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.
 In some cases, you need to provide options to alter GraphQL's execution behavior
@@ -312,6 +315,8 @@ type __Type {
     ofType: __Type
     # may be non-null for custom SCALAR, otherwise null.
     specifiedByURL: String
+    # must be non-null for INPUT_OBJECT, otherwise null.
+    isOneOf: Boolean
 }
 
 "An enum describing what kind of type a given '__Type' is."
diff --git a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/astvalidation/operation_rule_all_variable_uses_defined.go b/app/v2/pkg/astvalidation/operation_rule_all_variable_uses_defined.go
index bc9d098..b868ff9 100644
--- a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/astvalidation/operation_rule_all_variable_uses_defined.go
+++ b/app/v2/pkg/astvalidation/operation_rule_all_variable_uses_defined.go
@@ -53,5 +53,5 @@ func (a *allVariableUsesDefinedVisitor) EnterArgument(ref int) {
 
 	// at this point we're safe to say this variable was not defined on the root operation of this argument
 	argumentName := a.operation.ArgumentNameBytes(ref)
-	a.StopWithExternalErr(operationreport.ErrVariableNotDefinedOnArgument(variableName, argumentName))
+	a.StopWithExternalErr(operationreport.ErrVariableNotDefinedOnArgument(variableName, argumentName, a.operation.Arguments[ref].Value.Position))
 }
diff --git a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/astvalidation/operation_rule_values.go b/app/v2/pkg/astvalidation/operation_rule_values.go
index 5030117..f699b02 100644
--- a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/astvalidation/operation_rule_values.go
+++ b/app/v2/pkg/astvalidation/operation_rule_values.go
@@ -11,6 +11,8 @@ import (
 	"github.com/wundergraph/graphql-go-tools/v2/pkg/operationreport"
 )
 
+const oneOfDirectiveName = "oneOf"
+
 // Values validates if values are used properly
 func Values() Rule {
 	return func(walker *astvisitor.Walker) {
@@ -54,7 +56,7 @@ func (v *valuesVisitor) EnterArgument(ref int) {
 	if value.Kind == ast.ValueKindVariable {
 		_, exists := v.variableDefinition(value.Ref)
 		if !exists {
-			v.StopWithExternalErr(operationreport.ErrVariableNotDefinedOnOperation(v.operation.VariableValueNameBytes(value.Ref), []byte("")))
+			v.StopWithExternalErr(operationreport.ErrVariableNotDefinedOnOperation(v.operation.VariableValueNameBytes(value.Ref), []byte(""), value.Position))
 			return
 		}
 
@@ -430,6 +432,29 @@ func (v *valuesVisitor) valueSatisfiesInputObjectTypeDefinition(value ast.Value,
 		return false
 	}
 
+	if v.definition.NodeHasDirectiveByNameString(ast.Node{Kind: ast.NodeKindInputObjectTypeDefinition, Ref: inputObjectTypeDefinition}, oneOfDirectiveName) {
+		return v.objectValueSatisfiesOneOfInputObject(value, inputObjectTypeDefinition) && valid
+	}
+
+	return true
+}
+
+func (v *valuesVisitor) objectValueSatisfiesOneOfInputObject(value ast.Value, inputObjectTypeDefinition int) bool {
+	fields := v.operation.ObjectValues[value.Ref].Refs
+	typeName := v.definition.InputObjectTypeDefinitionNameBytes(inputObjectTypeDefinition)
+
+	if len(fields) != 1 {
+		v.Report.AddExternalError(operationreport.ErrOneOfInputObjectMustSpecifyExactlyOneKey(typeName, value.Position))
+		return false
+	}
+
+	fieldValue := v.operation.ObjectFieldValue(fields[0])
+	if fieldValue.Kind == ast.ValueKindNull {
+		fieldName := v.operation.ObjectFieldNameBytes(fields[0])
+		v.Report.AddExternalError(operationreport.ErrOneOfInputObjectFieldMustBeNonNull(typeName, fieldName, fieldValue.Position))
+		return false
+	}
+
 	return true
 }
 
diff --git a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/astvalidation/operation_validation_test.go b/app/v2/pkg/astvalidation/operation_validation_test.go
index 57e056f..fa803d8 100644
--- a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/astvalidation/operation_validation_test.go
+++ b/app/v2/pkg/astvalidation/operation_validation_test.go
@@ -3960,6 +3960,46 @@ type Query {
 					}
 					`, Values(), Valid)
 			})
+			t.Run("oneOf input objects", func(t *testing.T) {
+				definition := `
+					directive @oneOf on INPUT_OBJECT
+
+					schema {
+						query: Query
+					}
+
+					scalar String
+					scalar Boolean
+
+					input Choice @oneOf {
+						cat: String
+						dog: String
+					}
+
+					type Query {
+						pet(input: Choice): Boolean
+					}
+				`
+
+				t.Run("valid with exactly one non-null field", func(t *testing.T) {
+					runWithDefinition(t, definition, `query { pet(input: {cat: "Garfield"}) }`, Values(), Valid)
+				})
+
+				t.Run("invalid with no fields", func(t *testing.T) {
+					runWithDefinition(t, definition, `query { pet(input: {}) }`, Values(), Invalid,
+						withValidationErrors(`OneOf Input Object "Choice" must specify exactly one key.`))
+				})
+
+				t.Run("invalid with multiple fields", func(t *testing.T) {
+					runWithDefinition(t, definition, `query { pet(input: {cat: "Garfield", dog: "Odie"}) }`, Values(), Invalid,
+						withValidationErrors(`OneOf Input Object "Choice" must specify exactly one key.`))
+				})
+
+				t.Run("invalid with null field", func(t *testing.T) {
+					runWithDefinition(t, definition, `query { pet(input: {cat: null}) }`, Values(), Invalid,
+						withValidationErrors(`Field "Choice.cat" must be non-null.`))
+				})
+			})
 			t.Run("with boolean input", func(t *testing.T) {
 				runWithDefinition(t, wundergraphSchema, `
 					query QueryWithBooleanInput($a: Boolean) {
@@ -3997,6 +4037,26 @@ type Query {
 						`Variable "$b" of type "Boolean" used in position expecting type "String"`,
 					))
 			})
+			t.Run("undefined variable includes source position", func(t *testing.T) {
+				definition := mustDocument(astparser.ParseGraphqlDocumentString(`
+					schema { query: Query }
+					scalar String
+					scalar Boolean
+					type Query { pet(name: String): Boolean }
+				`))
+				operation := mustDocument(astparser.ParseGraphqlDocumentString(`query { pet(name: $name) }`))
+				report := operationreport.Report{}
+
+				validator := &OperationValidator{}
+				validator.RegisterRule(Values())
+
+				result := validator.Validate(&operation, &definition, &report)
+
+				require.Equal(t, Invalid, result)
+				require.Len(t, report.ExternalErrors, 1)
+				assert.Equal(t, `variable: name not defined on operation: `, report.ExternalErrors[0].Message)
+				assert.Equal(t, []operationreport.Location{{Line: 1, Column: 19}}, report.ExternalErrors[0].Locations)
+			})
 
 			t.Run("with variables inside an input object", func(t *testing.T) {
 				run(t, `
diff --git a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/datasource/introspection_datasource/fixtures/schema_introspection.golden b/app/v2/pkg/engine/datasource/introspection_datasource/fixtures/schema_introspection.golden
index 0064f2d..1043350 100644
--- a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/datasource/introspection_datasource/fixtures/schema_introspection.golden
+++ b/app/v2/pkg/engine/datasource/introspection_datasource/fixtures/schema_introspection.golden
@@ -350,6 +350,16 @@
       ],
       "isRepeatable": false,
       "__typename": "__Directive"
+    },
+    {
+      "name": "oneOf",
+      "description": "Requires exactly one field to be supplied and that field must not be null.",
+      "locations": [
+        "INPUT_OBJECT"
+      ],
+      "args": [],
+      "isRepeatable": false,
+      "__typename": "__Directive"
     }
   ],
   "__typename": "__Schema"
diff --git a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/datasource/introspection_datasource/fixtures/schema_introspection_with_custom_root_operation_types.golden b/app/v2/pkg/engine/datasource/introspection_datasource/fixtures/schema_introspection_with_custom_root_operation_types.golden
index 0e8d299..d054853 100644
--- a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/datasource/introspection_datasource/fixtures/schema_introspection_with_custom_root_operation_types.golden
+++ b/app/v2/pkg/engine/datasource/introspection_datasource/fixtures/schema_introspection_with_custom_root_operation_types.golden
@@ -498,6 +498,16 @@
       ],
       "isRepeatable": false,
       "__typename": "__Directive"
+    },
+    {
+      "name": "oneOf",
+      "description": "Requires exactly one field to be supplied and that field must not be null.",
+      "locations": [
+        "INPUT_OBJECT"
+      ],
+      "args": [],
+      "isRepeatable": false,
+      "__typename": "__Directive"
     }
   ],
   "__typename": "__Schema"
diff --git a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/datasource/introspection_datasource/source_test.go b/app/v2/pkg/engine/datasource/introspection_datasource/source_test.go
index bb4a911..1009bcd 100644
--- a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/engine/datasource/introspection_datasource/source_test.go
+++ b/app/v2/pkg/engine/datasource/introspection_datasource/source_test.go
@@ -41,6 +41,36 @@ func TestSource_Load(t *testing.T) {
 	t.Run("schema introspection with custom root operation types", run(testSchemaWithCustomRootOperationTypes, `{"request_type":1}`, `schema_introspection_with_custom_root_operation_types`))
 	t.Run("type introspection", run(testSchema, `{"request_type":2,"type_name":"Query"}`, `type_introspection`))
 	t.Run("type introspection of not existing type", run(testSchema, `{"request_type":2,"type_name":"NotExisting"}`, `not_existing_type`))
+	t.Run("type introspection of oneOf input object", func(t *testing.T) {
+		def, report := astparser.ParseGraphqlDocumentString(`
+			directive @oneOf on INPUT_OBJECT
+
+			input PetInput @oneOf {
+				cat: String
+				dog: String
+			}
+
+			type Query {
+				pet(input: PetInput): Boolean
+			}
+		`)
+		require.False(t, report.HasErrors())
+		require.NoError(t, asttransform.MergeDefinitionWithBaseSchema(&def))
+
+		var data introspection.Data
+		gen := introspection.NewGenerator()
+		gen.Generate(&def, &report, &data)
+		require.False(t, report.HasErrors())
+
+		buf := &bytes.Buffer{}
+		source := &Source{introspectionData: &data}
+		require.NoError(t, source.Load(context.Background(), []byte(`{"request_type":2,"type_name":"PetInput"}`), buf))
+
+		var fullType introspection.FullType
+		require.NoError(t, json.Unmarshal(buf.Bytes(), &fullType))
+		require.NotNil(t, fullType.IsOneOf)
+		require.True(t, *fullType.IsOneOf)
+	})
 }
 
 const testSchema = `
diff --git a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/introspection/converter.go b/app/v2/pkg/introspection/converter.go
index 22a37ea..8325e88 100644
--- a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/introspection/converter.go
+++ b/app/v2/pkg/introspection/converter.go
@@ -126,10 +126,16 @@ func (j *JsonConverter) importInputObject(fullType *FullType) error {
 		return err
 	}
 
-	j.doc.ImportInputObjectTypeDefinition(
+	var directiveRefs []int
+	if fullType.IsOneOf != nil && *fullType.IsOneOf {
+		directiveRefs = append(directiveRefs, j.doc.ImportDirective(OneOfDirectiveName, nil))
+	}
+
+	j.doc.ImportInputObjectTypeDefinitionWithDirectives(
 		fullType.Name,
 		fullType.Description,
-		argRefs)
+		argRefs,
+		directiveRefs)
 
 	return nil
 }
diff --git a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/introspection/converter_test.go b/app/v2/pkg/introspection/converter_test.go
index 0abc628..0bf7809 100644
--- a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/introspection/converter_test.go
+++ b/app/v2/pkg/introspection/converter_test.go
@@ -10,8 +10,10 @@ import (
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 
+	"github.com/wundergraph/graphql-go-tools/v2/pkg/ast"
 	"github.com/wundergraph/graphql-go-tools/v2/pkg/astparser"
 	"github.com/wundergraph/graphql-go-tools/v2/pkg/astprinter"
+	"github.com/wundergraph/graphql-go-tools/v2/pkg/asttransform"
 	"github.com/wundergraph/graphql-go-tools/v2/pkg/testing/goldie"
 )
 
@@ -74,3 +76,37 @@ func BenchmarkJsonConverter_GraphQLDocument(b *testing.B) {
 		_, _ = converter.GraphQLDocument(buf)
 	}
 }
+
+func TestJSONConverter_GraphQLDocument_OneOfInputObject(t *testing.T) {
+	definition, report := astparser.ParseGraphqlDocumentString(`
+		directive @oneOf on INPUT_OBJECT
+
+		input PetInput @oneOf {
+			cat: String
+			dog: String
+		}
+
+		type Query {
+			pet(input: PetInput): Boolean
+		}
+	`)
+	require.False(t, report.HasErrors())
+	require.NoError(t, asttransform.MergeDefinitionWithBaseSchema(&definition))
+
+	gen := NewGenerator()
+	var data Data
+	gen.Generate(&definition, &report, &data)
+	require.False(t, report.HasErrors())
+
+	outputPretty, err := json.MarshalIndent(data, "", "  ")
+	require.NoError(t, err)
+
+	converter := JsonConverter{}
+	doc, err := converter.GraphQLDocument(bytes.NewBuffer(outputPretty))
+	require.NoError(t, err)
+
+	node, ok := doc.Index.FirstNodeByNameStr("PetInput")
+	require.True(t, ok)
+	require.Equal(t, ast.NodeKindInputObjectTypeDefinition, node.Kind)
+	require.True(t, doc.NodeHasDirectiveByNameString(node, OneOfDirectiveName))
+}
diff --git a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/introspection/fixtures/starwars_introspected.golden b/app/v2/pkg/introspection/fixtures/starwars_introspected.golden
index 5bb9e05..f73c653 100644
--- a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/introspection/fixtures/starwars_introspected.golden
+++ b/app/v2/pkg/introspection/fixtures/starwars_introspected.golden
@@ -1588,7 +1588,8 @@
         ],
         "interfaces": [],
         "possibleTypes": [],
-        "__typename": "__Type"
+        "__typename": "__Type",
+        "isOneOf": false
       },
       {
         "kind": "INPUT_OBJECT",
@@ -1655,7 +1656,8 @@
         ],
         "interfaces": [],
         "possibleTypes": [],
-        "__typename": "__Type"
+        "__typename": "__Type",
+        "isOneOf": false
       },
       {
         "kind": "OBJECT",
diff --git a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/introspection/generator.go b/app/v2/pkg/introspection/generator.go
index 820483f..435b292 100644
--- a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/introspection/generator.go
+++ b/app/v2/pkg/introspection/generator.go
@@ -13,6 +13,7 @@ const (
 	DeprecatedDirectiveName  = "deprecated"
 	DeprecationReasonArgName = "reason"
 	SpecifiedByDirectiveName = "specifiedBy"
+	OneOfDirectiveName       = "oneOf"
 )
 
 type Generator struct {
@@ -315,6 +316,8 @@ func (i *introspectionVisitor) EnterInputObjectTypeDefinition(ref int) {
 	i.currentType.Kind = INPUTOBJECT
 	i.currentType.Name = i.definition.InputObjectTypeDefinitionNameString(ref)
 	i.currentType.Description = i.definition.InputObjectTypeDefinitionDescriptionString(ref)
+	isOneOf := i.definition.NodeHasDirectiveByNameString(ast.Node{Kind: ast.NodeKindInputObjectTypeDefinition, Ref: ref}, OneOfDirectiveName)
+	i.currentType.IsOneOf = &isOneOf
 }
 
 func (i *introspectionVisitor) LeaveInputObjectTypeDefinition(ref int) {
diff --git a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/introspection/generator_test.go b/app/v2/pkg/introspection/generator_test.go
index 690e849..800059b 100644
--- a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/introspection/generator_test.go
+++ b/app/v2/pkg/introspection/generator_test.go
@@ -6,8 +6,10 @@ import (
 	"testing"
 
 	"github.com/jensneuse/diffview"
+	"github.com/stretchr/testify/require"
 
 	"github.com/wundergraph/graphql-go-tools/v2/pkg/astparser"
+	"github.com/wundergraph/graphql-go-tools/v2/pkg/asttransform"
 	"github.com/wundergraph/graphql-go-tools/v2/pkg/testing/goldie"
 )
 
@@ -78,3 +80,44 @@ func TestGenerator_Generate_Interfaces_Implementing_Interfaces(t *testing.T) {
 		diffview.NewGoland().DiffViewBytes("interfaces_implements_interfaces", fixture, outputPretty)
 	}
 }
+
+func TestGenerator_Generate_OneOfInputObject(t *testing.T) {
+	definition, report := astparser.ParseGraphqlDocumentString(`
+		directive @oneOf on INPUT_OBJECT
+
+		input PetInput @oneOf {
+			cat: String
+			dog: String
+		}
+
+		type Query {
+			pet(input: PetInput): Boolean
+		}
+	`)
+	if report.HasErrors() {
+		t.Fatal(report)
+	}
+
+	require.NoError(t, asttransform.MergeDefinitionWithBaseSchema(&definition))
+
+	gen := NewGenerator()
+	var data Data
+	gen.Generate(&definition, &report, &data)
+	if report.HasErrors() {
+		t.Fatal(report)
+	}
+
+	petInput := data.Schema.TypeByName("PetInput")
+	require.NotNil(t, petInput)
+	require.NotNil(t, petInput.IsOneOf)
+	require.True(t, *petInput.IsOneOf)
+
+	var foundOneOf bool
+	for _, directive := range data.Schema.Directives {
+		if directive.Name == OneOfDirectiveName {
+			foundOneOf = true
+			break
+		}
+	}
+	require.True(t, foundOneOf)
+}
diff --git a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/introspection/introspection.go b/app/v2/pkg/introspection/introspection.go
index c799e64..229b9fa 100644
--- a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/introspection/introspection.go
+++ b/app/v2/pkg/introspection/introspection.go
@@ -70,6 +70,8 @@ type FullType struct {
 	TypeName      string    `json:"__typename"`
 	// may be non-null for custom SCALAR, otherwise null.
 	SpecifiedByURL *string `json:"specifiedByURL,omitempty"`
+	// must be non-null for INPUT_OBJECT, otherwise null.
+	IsOneOf *bool `json:"isOneOf,omitempty"`
 }
 
 func NewFullType() *FullType {
diff --git a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/operationreport/externalerror.go b/app/v2/pkg/operationreport/externalerror.go
index 8de9805..f572c5f 100644
--- a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/operationreport/externalerror.go
+++ b/app/v2/pkg/operationreport/externalerror.go
@@ -8,24 +8,26 @@ import (
 )
 
 const (
-	NotCompatibleTypeErrMsg                 = "%s cannot represent value: %s"
-	NotStringErrMsg                         = "%s cannot represent a non string value: %s"
-	NotIntegerErrMsg                        = "%s cannot represent non-integer value: %s"
-	BigIntegerErrMsg                        = "%s cannot represent non 32-bit signed integer value: %s"
-	NotFloatErrMsg                          = "%s cannot represent non numeric value: %s"
-	NotBooleanErrMsg                        = "%s cannot represent a non boolean value: %s"
-	NotIDErrMsg                             = "%s cannot represent a non-string and non-integer value: %s"
-	NotEnumErrMsg                           = `Enum "%s" cannot represent non-enum value: %s.`
-	NotAnEnumMemberErrMsg                   = `Value "%s" does not exist in "%s" enum.`
-	NullValueErrMsg                         = `Expected value of type "%s", found null.`
-	UnknownArgumentOnDirectiveErrMsg        = `Unknown argument "%s" on directive "@%s".`
-	UnknownArgumentOnFieldErrMsg            = `Unknown argument "%s" on field "%s.%s".`
-	UnknownTypeErrMsg                       = `Unknown type "%s".`
-	VariableIsNotInputTypeErrMsg            = `Variable "$%s" cannot be non-input type "%s".`
-	MissingRequiredFieldOfInputObjectErrMsg = `Field "%s.%s" of required type "%s" was not provided.`
-	UnknownFieldOfInputObjectErrMsg         = `Field "%s" is not defined by type "%s".`
-	DuplicatedFieldInputObjectErrMsg        = `There can be only one input field named "%s".`
-	ValueIsNotAnInputObjectTypeErrMsg       = `Expected value of type "%s", found %s.`
+	NotCompatibleTypeErrMsg                        = "%s cannot represent value: %s"
+	NotStringErrMsg                                = "%s cannot represent a non string value: %s"
+	NotIntegerErrMsg                               = "%s cannot represent non-integer value: %s"
+	BigIntegerErrMsg                               = "%s cannot represent non 32-bit signed integer value: %s"
+	NotFloatErrMsg                                 = "%s cannot represent non numeric value: %s"
+	NotBooleanErrMsg                               = "%s cannot represent a non boolean value: %s"
+	NotIDErrMsg                                    = "%s cannot represent a non-string and non-integer value: %s"
+	NotEnumErrMsg                                  = `Enum "%s" cannot represent non-enum value: %s.`
+	NotAnEnumMemberErrMsg                          = `Value "%s" does not exist in "%s" enum.`
+	NullValueErrMsg                                = `Expected value of type "%s", found null.`
+	UnknownArgumentOnDirectiveErrMsg               = `Unknown argument "%s" on directive "@%s".`
+	UnknownArgumentOnFieldErrMsg                   = `Unknown argument "%s" on field "%s.%s".`
+	UnknownTypeErrMsg                              = `Unknown type "%s".`
+	VariableIsNotInputTypeErrMsg                   = `Variable "$%s" cannot be non-input type "%s".`
+	MissingRequiredFieldOfInputObjectErrMsg        = `Field "%s.%s" of required type "%s" was not provided.`
+	UnknownFieldOfInputObjectErrMsg                = `Field "%s" is not defined by type "%s".`
+	DuplicatedFieldInputObjectErrMsg               = `There can be only one input field named "%s".`
+	ValueIsNotAnInputObjectTypeErrMsg              = `Expected value of type "%s", found %s.`
+	OneOfInputObjectMustSpecifyExactlyOneKeyErrMsg = `OneOf Input Object "%s" must specify exactly one key.`
+	OneOfInputObjectFieldMustBeNonNullErrMsg       = `Field "%s.%s" must be non-null.`
 )
 
 type ExternalError struct {
@@ -305,8 +307,9 @@ func ErrVariableTypeDoesntSatisfyInputValueDefinition(value, inputType, expected
 	return err
 }
 
-func ErrVariableNotDefinedOnOperation(variableName, operationName ast.ByteSlice) (err ExternalError) {
+func ErrVariableNotDefinedOnOperation(variableName, operationName ast.ByteSlice, position position.Position) (err ExternalError) {
 	err.Message = fmt.Sprintf("variable: %s not defined on operation: %s", variableName, operationName)
+	err.Locations = LocationsFromPosition(position)
 	return err
 }
 
@@ -320,8 +323,21 @@ func ErrVariableMustBeUnique(variableName, operationName ast.ByteSlice) (err Ext
 	return err
 }
 
-func ErrVariableNotDefinedOnArgument(variableName, argumentName ast.ByteSlice) (err ExternalError) {
+func ErrVariableNotDefinedOnArgument(variableName, argumentName ast.ByteSlice, position position.Position) (err ExternalError) {
 	err.Message = fmt.Sprintf("variable: %s not defined on argument: %s", variableName, argumentName)
+	err.Locations = LocationsFromPosition(position)
+	return err
+}
+
+func ErrOneOfInputObjectMustSpecifyExactlyOneKey(typeName ast.ByteSlice, position position.Position) (err ExternalError) {
+	err.Message = fmt.Sprintf(OneOfInputObjectMustSpecifyExactlyOneKeyErrMsg, typeName)
+	err.Locations = LocationsFromPosition(position)
+	return err
+}
+
+func ErrOneOfInputObjectFieldMustBeNonNull(typeName, fieldName ast.ByteSlice, position position.Position) (err ExternalError) {
+	err.Message = fmt.Sprintf(OneOfInputObjectFieldMustBeNonNullErrMsg, typeName, fieldName)
+	err.Locations = LocationsFromPosition(position)
 	return err
 }
 
diff --git a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/variablesvalidation/variablesvalidation.go b/app/v2/pkg/variablesvalidation/variablesvalidation.go
index 70bb603..7677314 100644
--- a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/variablesvalidation/variablesvalidation.go
+++ b/app/v2/pkg/variablesvalidation/variablesvalidation.go
@@ -20,6 +20,8 @@ type InvalidVariableError struct {
 	Message       string
 }
 
+const oneOfDirectiveName = "oneOf"
+
 func (e *InvalidVariableError) Error() string {
 	return e.Message
 }
@@ -325,6 +327,26 @@ func (v *variablesVisitor) renderVariableInvalidNullError(variableName []byte, t
 	v.err = v.newInvalidVariableError(fmt.Sprintf(`Variable "$%s" got invalid value null; Expected non-nullable type "%s" not to be null.`, string(variableName), typeName))
 }
 
+func (v *variablesVisitor) renderVariableOneOfMustSpecifyExactlyOneKeyError(typeName []byte) {
+	variableName := string(v.currentVariableName)
+	invalidValue := string(v.currentVariableValue.MarshalTo(nil))
+	var path string
+	if len(v.path) > 1 {
+		path = fmt.Sprintf(` at "%s"`, v.renderPath())
+	}
+	v.err = v.newInvalidVariableError(fmt.Sprintf(`%s%s; OneOf Input Object "%s" must specify exactly one key.`, v.invalidValueMessage(variableName, invalidValue), path, string(typeName)))
+}
+
+func (v *variablesVisitor) renderVariableOneOfFieldMustBeNonNullError(typeName, fieldName []byte) {
+	variableName := string(v.currentVariableName)
+	invalidValue := string(v.currentVariableValue.MarshalTo(nil))
+	var path string
+	if len(v.path) > 1 {
+		path = fmt.Sprintf(` at "%s"`, v.renderPath())
+	}
+	v.err = v.newInvalidVariableError(fmt.Sprintf(`%s%s; Field "%s.%s" must be non-null.`, v.invalidValueMessage(variableName, invalidValue), path, string(typeName), string(fieldName)))
+}
+
 func (v *variablesVisitor) traverseFieldDefinitionType(fieldTypeDefinitionNodeKind ast.NodeKind, fieldName ast.ByteSlice, jsonValue *astjson.Value, typeRef, inputFieldRef int) {
 	if v.definition.TypeIsNonNull(typeRef) {
 		if jsonValue == nil || jsonValue.Type() == astjson.TypeNull {
@@ -415,6 +437,20 @@ func (v *variablesVisitor) traverseNamedTypeNode(jsonValue *astjson.Value, typeN
 				return
 			}
 		}
+		if v.definition.NodeHasDirectiveByNameString(fieldTypeDefinitionNode, oneOfDirectiveName) {
+			if len(keys) != 1 {
+				v.renderVariableOneOfMustSpecifyExactlyOneKeyError(typeName)
+				return
+			}
+			selectedFieldName := keys[0]
+			selectedFieldValue := jsonValue.Get(unsafebytes.BytesToString(selectedFieldName))
+			if selectedFieldValue == nil || selectedFieldValue.Type() == astjson.TypeNull {
+				v.pushObjectPath(selectedFieldName)
+				v.renderVariableOneOfFieldMustBeNonNullError(typeName, selectedFieldName)
+				v.popPath()
+				return
+			}
+		}
 	case ast.NodeKindScalarTypeDefinition:
 		switch unsafebytes.BytesToString(typeName) {
 		case "String":
diff --git a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/variablesvalidation/variablesvalidation_test.go b/app/v2/pkg/variablesvalidation/variablesvalidation_test.go
index 754a247..48344ca 100644
--- a/tmp/agent-patch-flux-pr-1308.1-of-1.2026-02-28__13-38-10__gpt-5-4/app/v2/pkg/variablesvalidation/variablesvalidation_test.go
+++ b/app/v2/pkg/variablesvalidation/variablesvalidation_test.go
@@ -509,6 +509,57 @@ func TestVariablesValidation(t *testing.T) {
 		assert.Equal(t, `Variable "$bar" of required type "Foo!" was not provided.`, err.Error())
 	})
 
+	t.Run("oneOf input object variable with exactly one non-null field", func(t *testing.T) {
+		tc := testCase{
+			schema: `directive @oneOf on INPUT_OBJECT
+				input PetInput @oneOf { cat: String dog: String }
+				type Query { hello(arg: PetInput!): String }`,
+			operation: `query Foo($input: PetInput!) { hello(arg: $input) }`,
+			variables: `{"input":{"cat":"Garfield"}}`,
+		}
+		err := runTest(t, tc)
+		require.NoError(t, err)
+	})
+
+	t.Run("oneOf input object variable with no fields", func(t *testing.T) {
+		tc := testCase{
+			schema: `directive @oneOf on INPUT_OBJECT
+				input PetInput @oneOf { cat: String dog: String }
+				type Query { hello(arg: PetInput!): String }`,
+			operation: `query Foo($input: PetInput!) { hello(arg: $input) }`,
+			variables: `{"input":{}}`,
+		}
+		err := runTest(t, tc)
+		require.Error(t, err)
+		assert.Equal(t, `Variable "$input" got invalid value; OneOf Input Object "PetInput" must specify exactly one key.`, err.Error())
+	})
+
+	t.Run("oneOf input object variable with multiple fields", func(t *testing.T) {
+		tc := testCase{
+			schema: `directive @oneOf on INPUT_OBJECT
+				input PetInput @oneOf { cat: String dog: String }
+				type Query { hello(arg: PetInput!): String }`,
+			operation: `query Foo($input: PetInput!) { hello(arg: $input) }`,
+			variables: `{"input":{"cat":"Garfield","dog":"Odie"}}`,
+		}
+		err := runTest(t, tc)
+		require.Error(t, err)
+		assert.Equal(t, `Variable "$input" got invalid value; OneOf Input Object "PetInput" must specify exactly one key.`, err.Error())
+	})
+
+	t.Run("oneOf input object variable with null field", func(t *testing.T) {
+		tc := testCase{
+			schema: `directive @oneOf on INPUT_OBJECT
+				input PetInput @oneOf { cat: String dog: String }
+				type Query { hello(arg: PetInput!): String }`,
+			operation: `query Foo($input: PetInput!) { hello(arg: $input) }`,
+			variables: `{"input":{"cat":null}}`,
+		}
+		err := runTest(t, tc)
+		require.Error(t, err)
+		assert.Equal(t, `Variable "$input" got invalid value at "input.cat"; Field "PetInput.cat" must be non-null.`, err.Error())
+	})
+
 	t.Run("required string list field argument not provided", func(t *testing.T) {
 		tc := testCase{
 			schema:    `type Query { hello(arg: [String]!): String }`,