What the React 19 codemod doesn't tell you

The official React 19 migration codemod is useful. It handles the mechanical But it leaves three categories of silent breakage that don't surface until When you bump react to 19 and run yarn install, you get a wall of Either way, the real incompatibility is hidden. Your install succeeds. Radix UI 1.0.x reaches into element.ref internally. React 19 deprecated The codemod doesn't touch this. Your tests don't catch it. It shows up If your root tsconfig.json uses project references (files: [] + refe
The official React 19 migration codemod is useful. It handles the mechanical
stuff: ReactDOM.render → createRoot, string refs, prop-types cleanup.
But it leaves three categories of silent breakage that don't surface until
something breaks in production.
1. Peer-dep conflicts the installer swallows
When you bump react to 19 and run yarn install, you get a wall of
"incorrect peer dependency" warnings. Yarn proceeds anyway. npm either
blocks with ERESOLVE or silently overrides depending on your settings.
Either way, the real incompatibility is hidden. Your install succeeds.
Your CI is green. Your dependencies are broken.
2. element.ref time bombs
Radix UI 1.0.x reaches into element.ref internally. React 19 deprecated
this and added a compat shim — so it still works today. But the shim will
be removed in a future React minor, and when it is, every dialog, dropdown,
and popover in your app breaks at once.
The codemod doesn't touch this. Your tests don't catch it. It shows up
as a warning in stderr that's easy to miss:
3. tsc --noEmit false greens
If your root tsconfig.json uses project references (files: [] + references:
[...]), then tsc --noEmit checks zero files and reports zero errors.
The codemod runs tsc --noEmit to verify types. It passes. But your actual
type errors are still there — they only show up under tsc -b.
What I built
I ran into all three of these on a real migration and built keep-current
to catch them automatically.
It runs the full pipeline — codemods, dependency bump, install, tests,
type-check — then does a second-pass audit that surfaces what the codemod
marked as done but isn't.
Ran it against bulletproof-react (a well-known React architecture reference):
| Category | Green | Amber | Red |
|---|---|---|---|
| Dependencies | 4 | 7 | 4 |
| Type safety | 1 | 0 | 0 |
| Tests | 1 | 0 | 0 |
| Latent breakage | 0 | 1 | 0 |
RED: @storybook/react, lucide-react, react-helmet-async need major
version bumps before React 19 is safe.
AMBER: All Radix UI packages work today but reach into deprecated
element.ref — they'll break on the next React minor.
GREEN: react-router, zustand, react-query-auth already support React 19.
The codemod said "done." It wasn't.
Try it
npx keep-current migrate --from 18 --to 19 ./your-repo
Enter fullscreen mode Exit fullscreen mode
Zero runtime dependencies. Runs locally. Open source.


