Diagnostics and testing
Investigate failures by phase, recognize actual codes, and validate mounting, communication, and cleanup in the browser.
See versions, changes and requirements in Framework 4.0 and CLI 1.2.
Start with the phase that failed
console.log(wu.version);
console.log(wu.getStats());
console.log(wu.getAppInfo('catalog'));
console.log(wu.getSandboxInfo('catalog'));
console.table(wu.getManifestDiagnostics());
console.log(wu.inspect({ events: 20 }));
Registration, loading, mounting, updating, and teardown have different causes. Save the app name, URL, resolved entry, selector, actual mode, and original error. An empty screenshot cannot distinguish a failed load from a mounted root later erased by the shell renderer.
Symptom table
| Symptom | Concrete check | Resolution |
|---|---|---|
| App not registered | init completed; identical name in shell/manifest/define |
Wait for init and correct identity |
WU_MANIFEST_LOAD_FAILED |
Status, CORS, /wu.json response |
Serve real JSON from the registered base |
WU_MANIFEST_NAME_MISMATCH |
Downloaded name versus configuration | Publish that app’s manifest |
WU_MANIFEST_INVALID |
Fields, JSON, entry, and permissions | Fix the manifest; do not hide failure with defaults |
WU_PERMISSION_REQUIRED |
Required request without coverage | Deliberately adjust the request or host grant |
WU_CAPABILITY_DENIED |
Scoped operation and effective resource | Use an authorized path/channel |
emit returns false |
Identity, grants, and namespace | Check callback/scoped facade; do not assume an exception |
WU_APP_SCOPE_REVOKED |
API retained after unmount | Cancel work and obtain a new context on mount |
Container not found |
Selector resolved from document |
Light DOM slot exists before mount |
| Failed dynamically imported module | Entry, chunks, MIME, and CORS | Align the manifest with the actual build |
| Empty app without an error | Host reconciles slot children | Separate the mount node from the loading indicator |
| Invalid React hook | Two React copies or a different ReactDOM | Inject a consistent runtime into the adapter |
| Vue does not refresh state | Vue runtime unavailable when creating ref | Install the plugin/namespace and connect the subscription |
| RPC error without a handler | Provider not mounted yet | Order lifecycle operations or use a waiting state |
Resolve identity and startup conflicts
WU_APP_EXISTS means registration is attempting to occupy an existing name. Check wu.getAppInfo(name) and review which bootstrap registers that identity. An existing app’s configuration retains host grants; creating another wrapper does not replace them.
To check configuration and mounting separately, use explicit startup:
import { wu } from 'wu-framework';
await wu.init({ apps: [{ name: 'catalog', url: '/apps/catalog' }] });
console.log(wu.getAppInfo('catalog'));
try {
await wu.mount('catalog', '#catalog-slot');
} catch (error) {
console.error('No se pudo montar catalog', error);
console.log(wu.getSandboxInfo('catalog'));
throw error;
}
whenReady() waits for startup that has already begun; it does not start the runtime. In integrations with parent/child effects, coordinate startup first, then mounting. wu.app() registers lazily on mount and shares that registration between concurrent mounts of the same wrapper; see lifecycle for its reference and cleanup contract.
Avoid using WuApp.destroy() and recreating the same name to update configuration: that method does not clear all related registrations. Unmount the renderer for a normal transition, or reinitialize the entire core when the shell must replace its composition.
Mount recovery
The error boundary has handlers for network, script loading, mounting, timeout, and generic fallback. The core interprets retry requests and reruns mounting with cleanup; it preserves the definition because importing a cached ESM module again does not reevaluate it.
The core recognizes retry and retry-with-longer-timeout in its retry path. An action name returned by a handler does not itself change a URL or timeout: configure and verify the behavior the core consumes. Classification also uses error names and message fragments; preserve the full error for diagnosis.
The generic function registered last among default handlers accepts everything. register() appends to the end, so a handler added later may sit behind the generic handler and not run as the user expects. Check ordering before basing business recovery on extensions to this system.
Repository tests
Suites separate runtime units, subsystem integration, and security boundaries. Choose the level matching the contract you are changing:
npm run test:unit
npm run test:integration
npm run test:security
npm run test:coverage
test:package builds and exercises the distribution contract. test:mcp runs the separate MCP package. A suite importing src alone does not prove the dist package delivers correct exports/chunks.
A registration regression must execute WuCore and its actual validation. You can replace manifest downloads and the renderer to control the scenario, but a fully mocked core does not check identity, grants, or cleanup. For concurrency, defer the manifest response and start two mounts before resolving it; verify both the single registration and mount references.
Before publishing runtime changes, run the relevant suite and package tests against the build you will distribute.
Browser acceptance
A useful polyglot system test mounts at least two renderers, changes shared state, and verifies both reflect the value. Then unmount one, emit again, and confirm its callbacks do not run. Finally, remount and verify there are no duplicate listeners.
For CSS failures, compare styleMode, ShadowRoot stylesheets, and ownership. For HMR or production, test both the Vite server and compiled assets. For SSR, confirm content exists in the first response and hydration preserves that DOM without duplication.
Implementation references
Inspection: src/core/wu-core.js; recovery: src/core/wu-core.js; error boundary: src/core/wu-error-boundary.js and src/core/wu-error-boundary.js; wrapper: src/core/wu-app.js; duplicate detection: src/core/wu-core.js; scripts: package.json. Tests: tests/unit/final-hardening-regressions.test.js, tests/unit/shared-container-navigation.test.js, tests/unit/props-channel.test.js, tests/integration/multi-app-isolation.test.js.
When upgrading to 4.0, compare error.code, not message text: core errors use codes such as WU_APP_NOT_REGISTERED, WU_CONTAINER_NOT_FOUND, WU_APP_NOT_DEFINED, WU_DEFINE_TIMEOUT and WU_CONTAINER_OCCUPIED. Contracts use WU_CAPABILITY_*. The error boundary sends unrecoverable failures directly to the fallback; it does not choose retries by searching message words.