2026-06-08

Build Passes, Screen Dies — The React 19 Runtime

The bug I wrestled with longest had bizarre symptoms. npm run build passed cleanly, the dev server returned 200, and yet the browser screen went stark white and died.
I opened the console and found a single line.

Cannot read properties of undefined (reading 'ReactCurrentOwner')

At first I suspected my own components, but they were fine.
The cause was way down below, in the runtime.

The crux is that package.json lies.
My dependencies listed react 18, but Next 16's App Router runs client components with its own bundled (vendored) React 19 runtime, independently of that version.
The React I believed I had installed was not the React actually running in the browser.

R3F v8 tripped over exactly that gap.
v8 depends on internal APIs that were removed in React 19 (like ReactCurrentOwner), and the 19 runtime simply doesn't have them.
So it crashed reading undefined from the moment the module was evaluated.
The build only looks at types and bundling, so it was fine; execution had no runtime API to call, so it died on the spot.

The fix was clean.
I bumped the whole stack to line up with React 19 — react 19, fiber 9, drei 10, postprocessing 3.
I didn't change a single line of my game code.
Just aligning the versions brought the screen back to life.

The lesson is clear.
A passing build and a 200 from the server are no proof that something "works." Runtime compatibility is something you only know by looking at the browser console yourself.

From the next post on, I move to the arcade physics that gave the game its feel.
Movement and jumping first.

Up next: Arcade physics — movement and jumping →