Definition
When interactions like click and submit stop working several at once on a server-rendered screen, it is usually not several bugs but one root cause: the client JavaScript never ran, so hydration failed wholesale.
Hydration: the process where the browser later attaches event listeners and state via JS to the static HTML the server produced, making it "come alive." Until that finishes, a button is just a picture. If the bundle dies at the parse/execute stage, hydration itself can't start or complete.
Why It Matters
Bug reports arrive as several symptoms — "the toggle won't work," "the login button won't work," "submit won't work." Treat them as three bugs and dig into each and you waste time. In a server-rendered (SSR) app, what these symptoms have in common is that they are all event handlers. The HTML the server sent looks perfectly fine, but if the client JS that attaches events on top of it dies, every interaction on the screen disappears at once. The screen still looks normal, which is more confusing.
How It Works
Two branches where bundle execution dies:
- Parse failure: an old browser can't read new syntax, so the whole file halts with a
SyntaxError. After the first error, not one line runs. - Runtime failure: calling a missing API throws a
TypeErrorand halts mid-hydration. If that code is on the initial execution path, all interactions on the screen die.
This differs from a hydration mismatch (a separate case where server and client markup differ so React discards the tree). A mismatch is "it runs but the result is off"; what we mean here is "it doesn't run at all."
Practical Application
- First hypothesize the several symptoms as "one execution failure," not "N bugs."
- Split by the kind of first console error:
SyntaxError→ syntax (transpile),TypeError: is not a function→ missing API (polyfill). - Fix the causal layer (down-level syntax, polyfill missing APIs).
- If it reproduces only on a specific browser/version, a compatibility (syntax/API) cause is likely.
Trade-offs
| Diagnostic approach | Upside | Cost |
|---|---|---|
| Per-symptom individual debugging | Start immediately | Miss the common cause → waste time |
| Common-root-cause hypothesis first | Solve in one shot | If the initial hypothesis is wrong, detour |
When Not to Use
- When only a single feature fails — that may be a genuinely individual bug, so don't force the common-cause hypothesis.
- When a server/client markup mismatch warning is clear — that is a mismatch, not a failure to fire, so the remedy differs.
Common Mistakes
- Ruling out hydration because "it rendered" since the screen is visible.
- Opening a separate ticket per symptom and investigating the same cause three times.
- Touching only the UI without looking at the first console error.
Related Concepts
- syntax-transpilation-vs-runtime-polyfill — The two causes that kill a bundle (syntax and API)
- ssr-hydration-mismatch — A separate case where it runs but server and client diverge
- browser-compat-interaction-smoke — A test that actually catches dead handlers