Skip to content

GraphQlArgumentBinder silently drops fields from extended input types for nested input objects #1418

@salbecknm

Description

@salbecknm

Description

Spring GraphQL correctly accepts and validates GraphQL input type extensions (extend input) at schema level.
However, when an extended input type is used nested inside another input object, the additional fields introduced by the extension are silently dropped during runtime binding.
This results in GraphQL input that is:

  • valid according to the schema,
  • but partially inaccessible from Java code.

This behavior makes input extensions effectively unusable for nested input types.

Actual Behavior

Given the following schema:

input AddressInput {
  street: String
}

extend input AddressInput {
  zipCode: String
}

input UserInput {
  name: String
  address: AddressInput
}

type Mutation {
  createUser(input: UserInput!): Boolean
}

And Java models:

class AddressInput {
  private String street;
}

class ExtendedAddressInput extends AddressInput {
  private String zipCode;
}

class UserInput {
  private AddressInput address;
}

Executing the mutation:

mutation {
  createUser(input: {
    name: "John",
    address: {
      street: "Main St",
      zipCode: "12345"
    }
  })
}

then the following occurs

  • Schema validation succeeds.
  • Execution proceeds without errors.
  • At runtime, UserInput.address is always bound as AddressInput.
  • The zipCode field is silently ignored and cannot be accessed.
  • No error or warning is raised.

Reproduction

A minimal Maven project ZIP is attached. To reproduce:

spring-graphql-input-extension-demo.zip

  1. Import the project
  2. Run the test GraphQlInputExtensionTest
  3. The test fails, demonstrating that a field defined via extend input is accepted by the schema but not bound to the Java input object at runtime.

Current workaround:
I implemented a local workaround that makes the extended input fields available at runtime, which confirms that the issue is confined to argument binding.
The workaround requires replacing internal framework classes and is therefore not suitable as a long-term solution.
I can provide details of the workaround, including the implementation, if that would be helpful.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions