Skip to content

schema-codegen generates nullable @strawberry.input fields as required (missing Python default), causing __init__() missing required keyword-only argument for {} inputs #4177

@dakl

Description

@dakl

schema-codegen generates nullable @strawberry.input fields as required (missing Python default), causing __init__() missing required keyword-only argument for {} inputs

Describe the bug

When using strawberry schema-codegen on an SDL that contains an input with a nullable field, the generated Python @strawberry.input class annotates the field as T | None but does not assign a default value (e.g. = strawberry.UNSET or = None).

Because Strawberry input classes are dataclasses, this makes the field a required keyword-only argument in __init__, even though the GraphQL field is nullable/optional and can be omitted (e.g. input: {}).

This leads to runtime errors like:

HealthResultInput.__init__() missing 1 required keyword-only argument: 'some_number'

Minimal reproduction

SDL (schema.graphql)

type HealthResult {
  someNumber: Int
}

input HealthResultInput {
  someNumber: Int
}

type Query {
  healthy(input: HealthResultInput!): HealthResult!
}

Generate code

strawberry schema-codegen schema.graphql -o schema.py

Generated output (problem)

import strawberry

@strawberry.input
class HealthResultInput:
    some_number: int | None  # <- no default, becomes required kw-only in __init__

Query that should work (field omitted)

query MyQuery {
  healthy(input: {}) {
    someNumber
  }
}

Actual result

GraphQL returns an error because HealthResultInput() cannot be constructed from {} due to the missing Python default:

{
  "data": null,
  "errors": [
    {
      "message": "HealthResultInput.__init__() missing 1 required keyword-only argument: 'some_number'",
      "path": ["healthy"]
    }
  ]
}

Expected behavior

For nullable fields in generated @strawberry.input classes, schema-codegen should emit a Python default so the field is truly optional at runtime, for example:

  • If the SDL field has no default:
    • generate = strawberry.UNSET (so omitted vs null can be distinguished), or at least = None
  • If the SDL field has a default (e.g. someNumber: Int = 5):
    • generate = 5

Example expected code (no SDL default):

@strawberry.input
class HealthResultInput:
    some_number: int | None = strawberry.UNSET

Example expected code (SDL default):

@strawberry.input
class HealthResultInput:
    some_number: int | None = 5

Environment

  • OS: macOS (darwin)
  • Python: 3.13.x
  • Strawberry: strawberry-graphql[cli,fastapi] >= 0.289.3
  • Command: strawberry schema-codegen …

Additional context / related

  • Input types docs (optional input fields need defaults): https://strawberry.rocks/docs/types/input-types
  • Schema-codegen docs: https://strawberry.rocks/docs/codegen/schema-codegen
  • Umbrella issue: https://github.com/strawberry-graphql/strawberry/issues/3097

Workarounds tried

  • Manually editing generated code to add = strawberry.UNSET / = None
  • Avoiding schema-codegen and writing input types code-first

Proposed fix

Update schema-codegen to:

  • propagate SDL default values into Python defaults for @strawberry.input fields, and/or
  • for nullable input fields with no SDL default, emit = strawberry.UNSET (or = None) so omitted fields don’t break input construction.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions