Skip to content

fix(orientation): defensive coerce in hashSeed to handle undefined objID#16

Merged
rulkens merged 1 commit intomainfrom
fix/fallback-orientation-bigint
May 6, 2026
Merged

fix(orientation): defensive coerce in hashSeed to handle undefined objID#16
rulkens merged 1 commit intomainfrom
fix/fallback-orientation-bigint

Conversation

@rulkens
Copy link
Copy Markdown
Owner

@rulkens rulkens commented May 6, 2026

Summary

Fixes the intermittent runtime crash on hover:

fallbackOrientation.ts:33 Uncaught (in promise) TypeError:
  Cannot mix BigInt and other types, use explicit conversions
    at hashSeed (fallbackOrientation.ts:33:24)
    at fallbackOrientation (fallbackOrientation.ts:56:26)
    at buildPointInfo (pointInfoBuilder.ts:267:14)
    at pointInfoFromGlobal (engine.ts:431:12)
    at setHovered (engine.ts:478:37)

Root cause

pointInfoBuilder calls fallbackOrientation(cloud.objIDs[idx]!, ra, dec). During a tier swap, the GPU pick texture can briefly return a global index that out-runs the just-uploaded cloud buffers — idx is out-of-bounds, BigUint64Array[oob] returns undefined, the ! non-null assertion is a TS-only lie, and undefined & 0xffffffffn throws.

Fix

Defensive coerce objID to 0n at hashSeed entry when it isn't a bigint. The resulting orientation stays deterministic (derived from RA/Dec, which is always valid) and produces exactly the same value an unmatched row would — so the user sees a stable orientation that matches the rest of the catalogue's "objID = 0n" path documented in the module header.

The deeper engine-side race (pick-texture index can briefly desync from the freshly-uploaded cloud buffer) is a separate concern. This PR keeps the renderer crash-free while that's investigated.

Test plan

  • npm run typecheck clean
  • New regression test covers fallbackOrientation(undefined as any, ra, dec) — passes
  • All existing fallbackOrientation tests pass
  • Manual: reproduce a tier swap (small → large), hover during the load — no console error

🤖 Generated with Claude Code

The pointInfoBuilder occasionally calls fallbackOrientation with a
cloud.objIDs[idx] value of `undefined` — happens during a tier swap
when the GPU pick texture briefly returns an index that out-runs the
just-uploaded cloud buffers, and `BigUint64Array[oob]` returns
undefined.  `undefined & 0xffffffffn` then throws "Cannot mix BigInt
and other types" and the hover handler crashes.

Coerce to 0n at hashSeed entry — the resulting orientation is still
deterministic (derived from RA/Dec) and matches what unmatched rows
already produce, so behavior is consistent with the existing
"objID = 0n" path documented in the module header.

Adds a regression test covering the undefined input case.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@rulkens rulkens merged commit 52da736 into main May 6, 2026
1 check passed
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