99designs / 99designs/gqlgen

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

Open
#4,263 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.