Skip to content

fix(schema): emit enum default values as enum values, not strings - #525

Merged
nicola-smartive merged 1 commit into
mainfrom
fix/enum-default-values
Jul 16, 2026
Merged

fix(schema): emit enum default values as enum values, not strings#525
nicola-smartive merged 1 commit into
mainfrom
fix/enum-default-values

Conversation

@smartive-nicolai

Copy link
Copy Markdown
Contributor

The bug

value() in src/schema/utils.ts decides whether to emit Kind.ENUM with:

: val instanceof Symbol
    ? { kind: Kind.ENUM, value: val.description! }

Symbols are primitives, so Symbol('X') instanceof Symbol is always false. That branch has never been reachable — meaning there is currently no way to express an enum default value at all.

So an enum default written the natural way, defaultValue: 'STRICT', falls into the typeof val === 'string' branch above and prints as:

mutationMode: MutationMode = "STRICT"   # quoted string

That is an invalid default for an enum. graphql 16 tolerated it; graphql 17 rejects it:

Mutation.createPortfolioAllocation(mutationMode:) has invalid default value:
Enum "MutationMode" cannot represent non-enum value: "STRICT".

Which means schema generation fails outright on graphql 17 — a hard blocker for consumers upgrading. Found while triaging a graphql 17 bump in zwei-wealth-platform.

Worth noting the SDL we emit today is already invalid; graphql 16's leniency is the only thing hiding it. So this is a correctness fix independent of 17.

The fix

One line — typeof val === 'symbol' — restoring the branch's evident intent.

  • Not a breaking change. The branch was unreachable, so no existing behaviour can depend on it.
  • No type change. Value is already unknown, so Symbol('STRICT') is accepted.
  • Consumers express enum defaults as defaultValue: Symbol('STRICT') → prints = STRICT.

Tests

Added tests/unit/enum-default-values.spec.ts covering enum-vs-string and symbols-in-lists. Verified it genuinely catches the bug: reverting the one-line fix turns it 2 failed / 1 passed, restoring it 3 passed. Full unit suite green (132 tests), lint clean.

Possible follow-up (deliberately not in this PR)

A string default on an enum-typed field still silently produces invalid SDL. Making value() type-aware (emit Kind.ENUM when the field's type is an enum) would remove the footgun entirely, but needs the enum registry threaded into the generic AST builders — a design call for the maintainers rather than something to smuggle into a bug fix.

value() checked `val instanceof Symbol` to decide whether to emit Kind.ENUM.
Symbols are primitives, so that is never true — the branch was unreachable and
there was no way to express an enum default at all.

Enum defaults passed as plain strings therefore fell into the STRING branch and
printed as `mutationMode: MutationMode = "STRICT"`. That is an invalid default
value for an enum: graphql 16 tolerated it, graphql 17 rejects it with
'Enum "X" cannot represent non-enum value', which blocks schema generation
entirely on graphql 17.

Fix the check to `typeof val === 'symbol'` so `defaultValue: Symbol('STRICT')`
prints as `= STRICT`. Value is already `unknown`, so no type change is needed,
and nothing can depend on the old behaviour because the branch never ran.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@nicola-smartive
nicola-smartive marked this pull request as ready for review July 16, 2026 17:00
@nicola-smartive
nicola-smartive merged commit eb4f15f into main Jul 16, 2026
23 checks passed
@nicola-smartive
nicola-smartive deleted the fix/enum-default-values branch July 16, 2026 17:00
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 29.2.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants