Troubleshooting
Hit a wall? Run jorvel diagnose first — it inspects Node, pnpm, ports, federation configs, and React-duplication risks. The issues below cover the rest.
Invalid hook call after loading a remote
Two copies of React are loaded. Symptoms include the console error Invalid hook call. Hooks can only be called inside of the body of a function component. firing the moment a remote mounts.
Checklist:
react+react-dommust besingleton: trueon both host and remote.- Host sets
eager: trueon shared React; remotes use the defaulteager: false. - Use native dynamic
import('remote/App')— not a runtimeloadRemoteModule()helper. Native imports let Rspack bridge the share scope at build time. - Run
jorvel diagnose— it will flag duplicate React versions discovered innode_modules.
Remote container not found after loading remoteEntry.js
The remoteEntry.jsscript loaded but the global container was never assigned. Usually the remote's name in its federation config does not match the name the host tries to load.
# Verify both sides
cat apps/dashboard/jorvel.federation.json | jq .name # "dashboard"
cat apps/shell/rspack.config.mjs | grep -A2 remotes # dashboard@...
# Regenerate if you renamed
jorvel federationDev-time 404 for a remote split chunk
Cross-origin chunks require CORS or same-origin. The fix is one flag:
jorvel dev --proxy-remotesThat proxies /jorvel/remotes/<name>/* on the host origin to http://localhost:<port>/* on the remote — no CORS dance required.
Routes not updated after adding a page
The file-based routes manifest is static. One of:
- Run
jorvel routesonce after adding/renaming a file insrc/pages/. - Run
jorvel routes --watchin a second terminal during dev — it regenerates on every change. - Add it to your
pnpm devalongsidejorvel devviaconcurrentlyornpm-run-all.
Hydration mismatch on SSR
The server rendered a different tree than the client. Most common causes:
Date.now(),Math.random(), locale-dependent number/date formatting.- Reading
window/documentin a shared component. - Persistent state (localStorage, cookies) consulted on the client but not the server.
- Third-party widgets that mutate the DOM before hydration (chat widgets, A/B testing snippets).
// Guard browser-only reads
const isClient = typeof window !== 'undefined';
const theme = isClient ? localStorage.getItem('theme') : 'light';
// Or defer to useEffect so SSR and first paint match
const [theme, setTheme] = React.useState<'light' | 'dark'>('light');
React.useEffect(() => {
setTheme((localStorage.getItem('theme') as 'light' | 'dark') ?? 'light');
}, []);CSP blocks the hydration script
Pass the same nonce to the CSP header and the hydration tag. A mismatch (or no nonce in either place) and the browser drops the script silently.
import { buildCsp, generateNonce } from '@jorvel/security';
import { serializeState } from '@jorvel/ssr';
const nonce = generateNonce();
response.setHeader('Content-Security-Policy', buildCsp({ nonce, strictDynamic: true }));
html = html.replace('</head>', serializeState(state, { nonce }) + '</head>');Rspack 1.x type-error on lazyCompilation
Put lazyCompilation: false at the top of rspack.config.mjs, not inside experiments. The shape moved in 1.7.7.
export default {
lazyCompilation: false, // ← top level
experiments: {
// lazyCompilation: false ← do NOT put it here
},
// ...
};Router fires twice in React StrictMode
StrictMode double-invokes effects in dev. Calling createRouter() inside a useEffectcreates two routers, two history subscriptions, and you'll see duplicated jorvel:navigate handling.
Fix: call getRouter() at module scope in bootstrap.tsx. It returns a singleton — the second invocation is a no-op.
Windows: pnpm install hangs / EPERM
- Make sure Windows Defender / corporate antivirus is not scanning
node_modulesin real time. Add a workspace-wide exclusion. - If symlinks fail, run PowerShell as Administrator once, or enable Developer Mode (Settings → Privacy & security → For developers).
- As a last resort:
pnpm install --shamefully-hoistfor a flat layout that plays nicer with tools that don't follow pnpm symlinks.
Port already in use
# Windows — find and stop the holder
Get-NetTCPConnection -LocalPort 3000 | Select-Object -ExpandProperty OwningProcess | ForEach-Object { Stop-Process -Id $_ -Force }# macOS / Linux
lsof -ti:3000 | xargs kill -9Or change the port in jorvel.app.json and re-run jorvel federation to update remote URLs in the host config.
Suspected memory leak in dev
HMR + Rspack + StrictMode together can hold onto event listeners if a remote forgets to clean up. Common culprits:
useEventBussubscribers without a returnedoff()in the cleanup phase.useNavigationEventshandlers that capture state via closure but never unmount.- Service Workers caching stale
remoteEntry.jsacross reloads — unregister the SW while iterating on a remote.
Still stuck?
jorvel diagnose for a full environment report, and set JORVEL_DEBUG=1 to surface stack traces. Open an issue at github.com/Ravikisha/JorvelJS/issues with the diagnose output attached.