Skip to content

🐛 core: fix tracking queries throwing after world.reset() - #299

Merged
ospira merged 1 commit into
pmndrs:canaryfrom
MaxFreedomPollard:fix/reset-tracking-masks
Oct 28, 2026
Merged

ospira merged 1 commit into
pmndrs:canaryfrom
MaxFreedomPollard:fix/reset-tracking-masks

Conversation

@MaxFreedomPollard

Copy link
Copy Markdown

world.reset() clears the tracking snapshots and masks of every Added, Removed and Changed modifier but never rebuilds them. Modifiers are usually created once at module level, so they outlive the reset, and the next query that uses one throws:

const Added = createAdded(); // module level

const world = createWorld();
world.spawn(Position);
world.query(Added(Position)); // [entity]

world.reset();
world.query(Added(Position)); // TypeError: Cannot read properties of undefined (reading '0')

With React's useQuery, which re-subscribes from its reset handler, the error comes out of world.reset() itself. main has the same code.

The fix runs the same loop ensureWorldRegistered uses for a newly registered world, so every tracking id gets fresh masks and tracking starts over as in a new world. A regression test is added to query-modifiers.test.ts.

I couldn't install the workspace (no npm registry access here), so vitest, tsc, oxlint and prettier were not run. I ran the @koota/core test files on Node 22 with type stripping and a small vitest-compatible shim: without the fix the new test throws the error above, and with it all 223 core tests pass.

🤖 Generated with Claude Code

reset cleared trackingSnapshots, dirtyMasks and changedMasks but never filled
them again. Tracking modifiers are usually created once at module level, so
they outlive the reset, and the next query that used one threw "Cannot read
properties of undefined (reading '0')" when createQueryInstance read the
missing snapshot. React's useQuery re-subscribes from a reset subscription, so
there the error came out of world.reset() itself.

A world that registers after a modifier was created gets masks for it in
ensureWorldRegistered. reset now does the same for every tracking id, from the
fresh entity masks, so tracking starts over the way it does in a new world.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@ospira
ospira merged commit bccbc5d into pmndrs:canary Oct 28, 2026
1 check passed
krispya pushed a commit that referenced this pull request Oct 28, 2026
reset cleared trackingSnapshots, dirtyMasks and changedMasks but never filled
them again. Tracking modifiers are usually created once at module level, so
they outlive the reset, and the next query that used one threw "Cannot read
properties of undefined (reading '0')" when createQueryInstance read the
missing snapshot. React's useQuery re-subscribes from a reset subscription, so
there the error came out of world.reset() itself.

A world that registers after a modifier was created gets masks for it in
ensureWorldRegistered. reset now does the same for every tracking id, from the
fresh entity masks, so tracking starts over the way it does in a new world.

Co-authored-by: Claude Opus 5.5 <[email protected]>
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.

2 participants