A host application using Module Federation goes into production, and users start seeing a blank panel where a remote-loaded micro-frontend should render, with a network error for remoteEntry.js in the console. What are the likely causes, and how should the host be built to degrade gracefully?
answer
- network fail vs version-negotiation fail vs remote-internal bug
- wrap each mount point in its own error boundary
- timeout + fallback on import()
- generic chunk-load-error hides the real cause
- treat remotes like a downstream network dependency
basics
~20 sIf the piece of a page that comes from another team's app fails to load, you probably have a broken link to their code, a version clash between shared libraries, or a bug in their code. The fix is to build the page so one missing piece shows a small fallback instead of breaking the whole page.
solid answer
~40 sA blank remote panel with a remoteEntry.js network error usually means one of three things: the remote is genuinely unreachable, for example a moved CDN path, a CORS misconfiguration, or a mid-deploy 404; a shared singleton dependency, commonly React, can't be version-negotiated between host and remote and throws during init; or the remote loaded fine but threw a runtime error inside its own code. To degrade gracefully, wrap every federated mount point in its own tightly-scoped error boundary so one remote's failure doesn't take down the page, wrap the import() call in a timeout with a fallback UI rather than letting a stalled load spin forever, and instrument observability specifically at the federation boundary, tagging errors with which remote and which shared-dependency negotiation was involved, since generic chunk-load-error buckets otherwise obscure root cause.
go deeper
Should recognize that a remote failing to load means something went wrong fetching outside code, and that the app shouldn't just crash because of it.
Should be able to name at least two distinct causes, such as a network or CDN issue versus a bug in the remote, and know that wrapping the mount point helps contain the failure.
Should distinguish all three root-cause categories — network, shared-version negotiation, and remote-internal bug — and design concrete mitigations such as error boundaries, import timeouts, and retry-with-cache-bust.
Should frame this as a distributed-systems reliability problem, propose organization-wide patterns such as federation-aware observability and staged remote rollout, and reason about acceptable blast radius per federated slot on the page.
## What the blank panel is telling you A blank panel accompanied by a network error for `remoteEntry.js` is the single most common production failure mode in Module Federation systems, and it almost always traces back to one of a small set of causes, each with a distinct signature once you know what to look for. ## The remote is unreachable The most frequent cause is simply that the remote is unreachable: - its CDN path changed, - a deployment removed the old version's assets before the host's cached page finished loading it, - a CORS policy on the remote's hosting doesn't allow the host's origin to fetch the script, - or the remote's own deploy is mid-rollout and briefly 404s. Because the host only discovers this at the moment a user's browser actually tries to `import()` the remote, not at the host's own build or deploy time, this class of failure is invisible to the host team's CI and only surfaces live, often intermittently, which is what makes it feel like 'it worked yesterday.' ## A shared-dependency version conflict A second, subtler cause is a shared-dependency version conflict: if `react` or another `singleton: true` shared package can't be resolved to a mutually compatible version between host and remote, Webpack's runtime can throw during the remote's `init()` call rather than rendering — the console error here typically mentions 'Shared module is not available for eager consumption' or an unsatisfied version range, distinct from a plain network failure but producing the same visible symptom of nothing rendering. Notably, this can happen even when remoteEntry.js itself loads with a clean 200 status, since the failure is in a later initialization step, not the fetch — a detail that quickly distinguishes it from the pure network-reachability cause during triage. ## A bug inside the remote itself A third cause is a runtime error inside the remote's own code once it does load, a genuine bug in that team's bundle, which, because the remote and host are compiled independently, can throw in a way the host's error boundaries were not written to expect, sometimes crashing more of the page than just the federated panel if the mount point isn't isolated. ## Building the host to degrade gracefully Building a host to degrade gracefully against this class of failure means treating every federated import as an operation that can fail, not as a guaranteed synchronous render. Concretely: - Every federated mount point should be wrapped in its own **error boundary**, scoped tightly around just that remote's rendered output, so a crash in the checkout remote shows a fallback only in the checkout panel rather than taking down the whole shell page. - The `import()` call itself should be wrapped with a **timeout** and explicit catch — a remote that hangs rather than errors, for example a slow or stalled network request, will otherwise leave the user staring at a loading spinner indefinitely, so a reasonable pattern is to race the import against a timeout and show a 'this section is temporarily unavailable' fallback if it doesn't resolve. - **Retrying** with a fresh cache-busted URL on failure can recover from transient CDN or deploy-window issues automatically. - Because these failures are runtime and often user-specific, such as a particular browser's cached remoteEntry.js version or a particular CDN edge node having stale content, production observability needs to specifically capture and alert on federation-boundary errors — plain frontend error tracking often buckets all of these under a generic chunk-load-error category unless the host explicitly tags which remote and which shared-dependency negotiation was involved, making root-causing painful without that extra instrumentation. ## A worked deploy-window scenario A concrete worked scenario makes the failure modes tangible: suppose a payments team redeploys their checkout remote and, for two minutes during the CDN's cache invalidation window, some edge nodes still serve the old remoteEntry.js referencing chunk hashes that the origin has already removed, while other edge nodes serve the new one. Users hitting the stale edge see a 404 for a specific chunk file mid-render, not for remoteEntry.js itself, producing an error that looks superficially like a remote-internal bug but is actually a deploy-propagation timing issue; teams that have seen this before recognize the signature, retry after a short delay, and often add a brief overlap window where both old and new chunk hashes remain live on the CDN specifically to eliminate this race. ## The architectural lesson At an architectural level, the deeper lesson these failures teach is that Module Federation converts what used to be a single application's internal wiring into a distributed system with its own partial-failure semantics — the same category of problem as a service calling a downstream microservice over HTTP, just happening inside the browser instead of between servers. Teams that treat federated remotes with the same rigor as any other network dependency, including health checks before promoting a new remote version, staged rollouts, error-boundary isolation, and explicit fallback UX, see this class of incident become rare and low-blast-radius; teams that treat `import('remote/Module')` as equivalent to a plain local import get paged the first time a remote's CDN has a bad five minutes.
- Why might a chunk-load-error style message obscure the real root cause of a Module Federation failure?Generic frontend error trackers often bucket any failed dynamic import, whether it's a lazy-loaded chunk, a Module Federation remote, or any other code-split boundary, under the same 'ChunkLoadError' category, so without explicit tagging of which remote and which dependency negotiation was involved, an engineer investigating the alert can't immediately tell a CDN outage apart from a version conflict apart from a bug in the remote's own code.
- What's a concrete way to prevent a stalled, not erroring, just hanging remote import from leaving a user staring at an infinite spinner?Race the import() call against a timeout using something like Promise.race, and if the timeout wins, render an explicit fallback such as 'this section is temporarily unavailable' instead of leaving the loading state indefinite; some teams also retry once with a cache-busted URL before giving up, to recover automatically from transient CDN blips.
- Why is scoping error boundaries tightly around each individual federated mount point important, rather than one boundary around the whole page?A single page-wide boundary means any one remote's failure takes down every other successfully-loaded remote and the host's own UI along with it; a boundary scoped to just that mount point contains the blast radius to the one panel that actually failed, which is the whole point of using independently deployed remotes in the first place.
It's the same problem a service calling a downstream microservice over HTTP has — the call can fail because the other service is down, because of an incompatible API contract, or because of a bug on their end — except this 'network call' happens inside the user's browser, so the same defensive patterns of timeouts, circuit breakers, and isolated failure blast radius apply, just implemented with error boundaries and import timeouts instead of server-side retry libraries.
saying these in an interview costs you the question
- treats a federated import() as guaranteed to succeed like a local import
- no error boundary scoped around individual remote mount points
- can't name at least two distinct root causes for a failed remote load
- assumes generic error tracking automatically distinguishes federation failures from other chunk-load errors
- no timeout or fallback strategy for a hanging, not erroring, remote load