Default values are ignored when an inline input object field is populated from an undefined variable
- Dominant language
- Go
- Stars
- 10.8k
- Forks
- 1.3k
- Avg merge
- 2d 36m
- Merged PRs (30d)
- 26
Description
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: https://github.com/vektah/gqlparser/issues/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.
Contributor guide
Assessment
This issue has not been assessed yet.