Troubleshooting
Start With the Build Mode
Check the generated manifest first:
dist/wp-content/themes/<theme>/assets/js/entrypoints.json
Its mode, scripts, and styles values show what WordPress is expected to load. The files listed there must exist in the deployed theme.
Development Works, Production Fails
Run:
npm run prod
npm run report:themes
If the browser reports jsxDEV is not a function, a production file contains React's development JSX runtime. Current ReactWP passes Webpack mode explicitly to Babel and the report fails when it detects this. Reinstall dependencies and rebuild instead of mixing files from different builds.
Also confirm that all scripts from entrypoints.json were deployed. The application entry depends on the framework/router/motion chunks being loaded first.
Missing style-loader
If Webpack cannot resolve style-loader, the local configs/node_modules does not match configs/package.json and its lock file.
From configs/, install dependencies again:
npm install
Theme builds extract imported SCSS with MiniCssExtractPlugin. Plugin and mu-plugin bundles can still use style-loader, so it remains a declared dependency.
Old Chunks Keep Accumulating
Current builds remove stale JavaScript, source maps, license files, and extracted CSS chunks after a successful emit. If old files remain:
- confirm the project has the current shared Webpack configuration
- confirm the build completed successfully
- inspect whether a deployment tool is merging old remote files instead of replacing them
- never delete the entire live theme while PHP is serving requests unless the deployment is atomic
Content Still Shows an Old Value
Identify the layer first:
- Reload the page fully. This clears route memory for the tab.
- Inspect
runtime.system.cacheVersionand Cache Storage. - Use ReactWP > Cache after the updated content/code is live.
- Purge the host or CDN HTML cache.
- Test in a new private window.
Static Route Falls Back to Client
Inspect the data-rwp-render value on #app. client means ReactWP intentionally did not use a fragment.
Check:
- the route's
route.render.mode assets/render/templates.jsonassets/render/static/manifest.json- the manifest and entry
cacheVersion - whether a post, menu, settings, or custom dependency tag invalidated the entry
- whether the generated path and language match the current route key
Run npm run generate again after setting RWP_SITE_URL. A missing or invalid fragment safely falls back to the browser runtime.
SSR Route Falls Back to Client
Confirm:
RWP_SSR_ENDPOINTincludes/render- WordPress and
serve.mjsuse the sameRWP_SSR_SECRET - the service is listening on loopback and
GET /healthsucceeds - the Node process can read
server.cjsand itschunks/directory - the template does not access browser-only globals during render
After a renderer failure, ReactWP briefly opens a circuit breaker. Fix the service, wait for that short window, then retry. WordPress remains available through the client fallback throughout the failure.
Hydration Warning
Hydration requires the server and first browser render to produce the same structure. Remove render-time randomness, timestamps, browser-only conditionals, and unstable locale output. Move DOM measurements and animation setup into effects.
When the registry name and template filename differ, set assetKey so initial template CSS is found. See Hybrid Rendering.
Images Work After Reload but Not Navigation
Check these points:
- the target selector exists after the next template mounts
- every repeated item uses a stable selector or React key
- filtered lists do not reuse
:nth-child()media targets for different content - the route declares the media group that contains the image
window.loader.criticalDisplayor the relevant deferred group settles
For dynamic lists and carousels, rendering the image from route data is often more reliable than assigning loader media by visual position.
REST Returns 403
For an admin request, verify that the browser sends valid WordPress cookies and X-WP-Nonce. Being logged into another tab does not help a cross-origin fetch unless credentials and cookie policy permit it.
For a public custom route, add its exact namespace/path through rwp_allowed_rest_routes, then keep the endpoint's own permission_callback appropriate to its data.
Route Endpoint Returns Home
The public and integrated route endpoint requires view:
/wp-json/reactwp/v1/route?view=/about/
path is not an alias. Include the query string inside view when it is part of route identity.
ScrollTrigger Is Wrong After Navigation
Create route-specific animations inside the template effect and kill them in its cleanup. Refresh after layout-changing content or deferred media is rendered:
useEffect(() => {
const context = gsap.context(() => {
// Route animation setup.
});
scroller.refresh();
return () => context.revert();
}, [route.key]);
Persistent shell components can use headerKey and footerKey from useRouteTransition() when they need to remount after a transition and recreate route-dependent effects.
Scroller Lock Does Not Reapply
Lock and unlock inside an effect. If the same component instance can render for multiple route changes, let the effect run for those renders or depend on the route key that should reacquire the lock.
useEffect(() => {
scroller.lock();
return () => scroller.unlock();
});
Call the ReactWP facade (scroller.lock()), not scroller.paused(). The facade owns both ScrollSmoother and native scroll fallback behavior.
Conflicting Asset Metadata
An image error such as Can't handle conflicting asset info for sourceFilename usually comes from stale production Webpack filesystem metadata. Current ReactWP disables Webpack filesystem cache in production. If an older project still has the issue, port the current shared Webpack configuration and rerun the production build.
SSG Fails on a Local HTTPS Certificate
An error containing DEPTH_ZERO_SELF_SIGNED_CERT means Node cannot build a trusted chain for the WordPress URL supplied through RWP_SITE_URL.
Current ReactWP adds operating-system CA certificates when the running Node version supports that API. Confirm that the Laragon or project root CA is installed in the Windows trusted root store, then test:
node --use-system-ca -e "fetch('https://example.test/wp-json/reactwp/v1/bootstrap').then(r => console.log(r.status))"
If the certificate is stored in a separate PEM file, use NODE_EXTRA_CA_CERTS for the build process. Never solve this by setting NODE_TLS_REJECT_UNAUTHORIZED=0; that disables verification for every TLS request in the process.
Verify Compression
The existence of .br and .gz files does not prove they are being served. Inspect the original .js or .css request in DevTools and look for:
Content-Encoding: br
Vary: Accept-Encoding
If absent, configure equivalent precompressed-file rules at the web server or CDN.