Skip to content

fix(graphile-schema): replace deepmerge with native preset composition to fix stack overflow - #900

Merged
pyramation merged 2 commits into
mainfrom
devin/1774509901-fix-deepmerge-stack-overflow
Mar 26, 2026
Merged

pyramation merged 2 commits into
mainfrom
devin/1774509901-fix-deepmerge-stack-overflow

Conversation

@pyramation

Copy link
Copy Markdown
Contributor

Summary

buildSchemaSDL used deepmerge to combine the base Graphile preset with caller-provided options. deepmerge recursively clones every nested object — including the pg Pool (EventEmitter internals) and the entire PostGraphile preset tree — which overflows the call stack ("Maximum call stack size exceeded") whenever any graphile option is passed, even {}.

The fix replaces deepmerge with Graphile's native extends mechanism to compose presets, and removes deepmerge as a dependency.

Before:

const preset = opts.graphile
  ? deepmerge(basePreset, opts.graphile)  // 💥 stack overflow
  : basePreset

After:

const preset = {
  extends: [ConstructivePreset, ...(opts.graphile?.extends ?? [])],
  plugins: opts.graphile?.plugins ?? [],
  pgServices: [ ... ],
}

Review & Testing Checklist for Human

  • Verify no caller passes preset keys beyond extends/plugins in opts.graphile. The old deepmerge forwarded all keys; the new code only forwards extends and plugins. If any call site passes e.g. disablePlugins, gather, schema, or other preset properties, they'll be silently dropped. Grep for buildSchemaSDL across constructive-db and constructive-hub.
  • Re-run the failing CI job (constructive-hub #68664351085) after publishing the updated graphile-schema to confirm all 7 API schema generations succeed end-to-end.
  • Confirm the pnpm-lock.yaml diff is only reformatting + deepmerge removal (no unintended dependency changes).

Notes

  • Reproduced locally: buildSchemaSDL({ database, schemas, graphile: {} }) overflows; without the graphile key it succeeds. Confirmed the fix resolves all test cases (0 node types through 52 node types).
  • The lock file diff is large due to pnpm reformatting resolution fields from multi-line to single-line — no functional dependency changes beyond removing deepmerge.

Link to Devin session: https://app.devin.ai/sessions/6c7e6bf137a34786827fc77a43a7a84a
Requested by: @pyramation

deepmerge recursively clones the entire PostGraphile preset tree and
pg Pool objects inside pgServices, which overflows the call stack.

Use Graphile's native `extends` mechanism to compose presets instead.
This preserves object identity and avoids cloning non-serializable
objects like database connection pools.

Fixes: Maximum call stack size exceeded during SDL generation
@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@pyramation
pyramation merged commit c21bcc5 into main Mar 26, 2026
43 checks passed
@pyramation
pyramation deleted the devin/1774509901-fix-deepmerge-stack-overflow branch March 26, 2026 07:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant