RMD021 — A random number was read while a value was being derived
Math.random(), crypto.randomUUID() and crypto.getRandomValues() are reported when
they are called while one of the four pure phases is running. The same call fails
differently in each, so the message differs with it:
- In a
render()the output depends on when it ran, so a server render and its hydration disagree and the markup is thrown away (RMD007). - In a
@computeit is quieter and worse: the answer is cached, so the value is frozen at the moment it was first asked for, and only a dependency the compute actually READ can refresh it — which may be never. - In a
@memoizedbuilder it is cached with the handler, keyed by the arguments, so every call to that handler uses the one value. The builder runs during a render, so without its own report the fix would look like a render problem. - In a hook's props callback it is the strangest of the four. The callback is cached on the signals it reads, and a random or clock value is not one of them — so it is frozen into the bag until something unrelated invalidates the callback, and then it jumps. As a query key: an entry that changes when somebody else's state moves, and never when yours does.
Read it once in @created and keep it in @state (or @persist, so it survives
hydration), take it as a prop, or read it in the event handler that needs it.
The clock is deliberately not watched here. The platform reads it behind your back —
an Event constructor stamps timeStamp — so a guard on it would report calls your app
never made, attributed to whichever component happened to be rendering. new Date() is
caught by RMD020 as a fresh
identity, and Date.now() only when a hydration disagrees
(RMD007). In a client-only app
nothing catches it at runtime, which is why
ramonda-check reads it out of the source instead, as
clock-read-while-rendering.
Next
- All diagnostics — every code the framework can report.
- Checking your app — the faults proved from the source, before anything runs.