From 706dd7661ca6c13632ef3c588a4d2dc4213f2de6 Mon Sep 17 00:00:00 2001 From: Anton Pascal Date: Thu, 28 May 2026 04:06:14 +0000 Subject: [PATCH] fix: guard onShelfMove against null cursorGroupRef (Sentry EDITOR-BC) Every other surface-move handler in use-placement-coordinator (onGridMove, onWallMove, onCeilingMove, onItemMove) already short-circuits when cursorGroupRef.current is null. onShelfMove was missed in PR #323 and went on to throw TypeError: Cannot read properties of null (reading 'rotation') 53,528 times in vercel-production between 2026-05-20 and 2026-05-27, all firing from the mitt event-emitter dispatch loop while a shelf hover stream raced with cursor unmount. The fix is a one-line guard matching the existing pattern; behavior is unchanged when cursorGroupRef is mounted. --- .../components/tools/item/use-placement-coordinator.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/editor/src/components/tools/item/use-placement-coordinator.tsx b/packages/editor/src/components/tools/item/use-placement-coordinator.tsx index 8edc1207d..192425502 100644 --- a/packages/editor/src/components/tools/item/use-placement-coordinator.tsx +++ b/packages/editor/src/components/tools/item/use-placement-coordinator.tsx @@ -1252,6 +1252,13 @@ export function usePlacementCoordinator(config: PlacementCoordinatorConfig): Rea const onShelfMove = (event: ShelfEvent) => { has3DPointerDrivenMoveRef.current = true + // Guard against null ref. The mitt event listener can fire after the + // component unmounts (or before the attaches), and the + // unguarded `cursorGroupRef.current.rotation.y = ...` write below was + // the source of EDITOR-BC (`Cannot read properties of null (reading + // 'rotation')`) — 53k+ events. Every other surface-move handler in + // this file already has this guard; onShelfMove was missed in #323. + if (!cursorGroupRef.current) return const ctx = getContext() if (ctx.state.surface !== 'shelf-surface') { // Cursor entered via a move event without an enter — try