Skip to content

Default values are ignored when an inline input object field is populated from an undefined variable #4263

Description

@surbhi-singh

When an input object field is set inline from a variable (e.g. { truthyBoolean: $truthyBoolean }) and that variable is left undefined, the schema's default value for the field isn't applied. Instead, the resolver receives nil. If the entire input object is passed as a variable, or if the field is omitted altogether, the default is applied as expected. This behavior is inconsistent.

Schema:

input DefaultInput {
    falsyBoolean:  Boolean = false
    truthyBoolean: Boolean = true
}

type Mutation {
    defaultInput(input: DefaultInput!): DefaultParametersMirror!
}

Operation (no variables provided, so $truthyBoolean is undefined):

mutation ($truthyBoolean: Boolean) {
    defaultInput(input: { truthyBoolean: $truthyBoolean }) {
        falsyBoolean
        truthyBoolean
    }
}

Expected:

  • truthyBoolean = true

  • falsyBoolean = false

    Actual:

  • falsyBoolean = false (default applied since it's absent from the object)

  • truthyBoolean = null (the resolver receives nil and the default is ignored)

The underlying issue appears to be in gqlparser. The parser materializes the inline object { truthyBoolean: $truthyBoolean } as {"truthyBoolean": nil} which means the key is present with a nil value. gqlgen's generated method unmarshalInputDefaultInput only fills a default value when the key is absent but skips it if it's present but is nil.

Reproduction:
It can be added as a subtest to codegen/testserver/singlefile/defaults_test.go in the test method TestDefaults

t.Run("default input field from undefined variable", func(t *testing.T) {
    resolvers.MutationResolver.DefaultInput = func(
        ctx context.Context,
        input DefaultInput,
    ) (*DefaultParametersMirror, error) {
        return &DefaultParametersMirror{
            FalsyBoolean:  input.FalsyBoolean,
            TruthyBoolean: input.TruthyBoolean,
        }, nil
    }

    var resp struct{ DefaultInput *DefaultParametersMirror }
    // No variables are provided, so $truthyBoolean is undefined.
    err := c.Post(`mutation ($truthyBoolean: Boolean) {
        defaultInput(input: { truthyBoolean: $truthyBoolean }) {
            falsyBoolean
            truthyBoolean
        }
    }`, &resp)
    require.NoError(t, err)
    assertDefaults(t, resp.DefaultInput) // fails: truthyBoolean is nil, wants true
})

Related gqlparser issue: vektah/gqlparser#347
However, because it appears directly in gqlgen, I'm opening this issue here for visibility and tracking. I’d be happy to work on a fix for this.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions