# 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](/docs/guides/releases/).


<span id="empieza-por-la-fase-que-falló"></span>

<span class="section-anchor" id="section-1"></span>

## Start with the phase that failed

```js
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.

<span id="tabla-de-síntomas"></span>

<span class="section-anchor" id="section-2"></span>

## 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 |

<span id="resolver-conflictos-de-identidad-y-arranque"></span>

<span class="section-anchor" id="section-3"></span>

## 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:

```js
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](/docs/framework/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.

<span id="recuperación-de-montaje"></span>

<span class="section-anchor" id="section-4"></span>

## 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.

<span id="pruebas-del-repositorio"></span>

<span class="section-anchor" id="section-5"></span>

## Repository tests

Suites separate runtime units, subsystem integration, and security boundaries. Choose the level matching the contract you are changing:

```bash
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.

<span id="aceptación-en-navegador"></span>

<span class="section-anchor" id="section-6"></span>

## 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.

<span id="referencia-de-implementación"></span>

<span class="section-anchor" id="section-7"></span>

## 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.