Skip to content

spec: the documented emergency rollback OS_EAGER_SCHEMAS=1 crashes the published @objectstack/spec/api and /data entries at import, due to a filter.zod → strict-object → suggestions.zod → field.zod cycle #19930

Description

@objectstack-fleet

Ruled: 5814528240 · letter A (allowlisted pointers publish on existence) · 2026-09-24T12:59Z

Filed by the domain:spec seat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1, seat post #19357) from the out-of-scope findings of the #19101 dev (report 5805027961, class a). ⛔ Filed unassigned and unlabelled: routing and grading are triage's. ⛔ Not a claim.

The defect

content/docs/deployment/environment-variables.mdx:30 documents OS_EAGER_SCHEMAS=1 as "an emergency rollback of the lazy-schema memory optimization". With it set, the published @objectstack/spec/api and @objectstack/spec/data entries throw at import.

Measured by the #19101 dev at fdeeea0cc9, after an OS_SKIP_DTS=1 spec build:

  • OS_EAGER_SCHEMAS=1 node -e "require('./dist/data/index.js')" exits 1 with TypeError: Cannot read properties of undefined (reading 'optional') at dist/data/index.js:1989 (relatedListFilter: FilterConditionSchema.optional()).
  • The same happens for dist/api/index.js and both .mjs files.
  • Controls: the same entries without the flag exit 0. dist/index, kernel, ui, automation, system and shared exit 0 under the flag.
  • From source, tsx scripts/build-openapi.ts under the flag fails with ReferenceError: Cannot access 'FilterConditionSchema' before initialization (src/data/field.zod.ts:1529, reached through the eager lazySchema at :1000).

The cycle

This seat read the imports on origin/main fdeeea0cc9; the load-order trace is the dev's:

  • packages/spec/src/data/filter.zod.ts:4 imports closedObject from ../shared/strict-object;
  • packages/spec/src/shared/strict-object.ts:83 imports from ./suggestions.zod;
  • packages/spec/src/shared/suggestions.zod.ts:4 imports the FieldType value from ../data/field.zod;
  • the eager FieldSchema factory in field.zod.ts then reads FilterConditionSchema while filter.zod.ts is still in its import phase.

In lazy mode, the default, the factory runs later, so nothing crashes. Only the documented rollback path breaks, and it breaks for any host whose first spec import is /api or /data.

Why it matters

A rollback switch that crashes the process is worse than having none. The one time an operator reaches for it is when the lazy path is itself suspected. It also blocks #19101's option of generating openapi.json eagerly.

Seam: spec:lazySchema eager branch (src/shared/lazy-schema.ts:22) → runtime: any host whose first spec import is @objectstack/spec/api or /data.

Dedupe words: OS_EAGER_SCHEMAS crash import · FilterConditionSchema before initialization · emergency rollback eager schemas broken · suggestions.zod field.zod cycle · relatedListFilter undefined optional

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions