perspective-dev/perspective · error · Error

Missing perspective-client.wasm

Error message

Missing perspective-client.wasm

What it means

`get_client()` resolves the client wasm used to create Perspective clients. It first checks whether a `<perspective-viewer>` custom element is registered (whose wasm can be reused); otherwise it relies on the global set by `init_client()`. If neither exists, the browser build has no client wasm available and throws "Missing perspective-client.wasm" — typically because `worker()`/`websocket()`/`createMessageHandler()` was called before any wasm was initialized.

Solutions

  1. Call `perspective.init_client(fetch('perspective-client.wasm'))` (or pass an ArrayBuffer/Response/initialized module) before creating workers or connections.
  2. Import/define the `<perspective-viewer>` custom element so its wasm can be reused, if your setup loads wasm through the viewer.
  3. If using a bundler, ensure the wasm plugin/asset pipeline includes perspective-client.wasm and the default init path isn't tree-shaken.
  4. Ensure the call happens after init, not at module-evaluation top level before init completes.

Example fix

// before
const worker = perspective.worker(); // throws: no wasm initialized
// after
await perspective.init_client(fetch("perspective-client.wasm"));
const worker = perspective.worker();
Defensive patterns

Strategy: try-catch

Validate before calling

const viewerDefined = !!customElements.get("perspective-viewer");
const clientReady = viewerDefined || clientWasmInitialized; // track your own init flag
if (!clientReady) await perspective.init_client(fetch("perspective-client.wasm"));

Type guard

function clientWasmAvailable(): boolean {
  return !!customElements.get("perspective-viewer") || clientWasmInitialized;
}

Try / catch

let worker;
try {
  worker = perspective.worker();
} catch (e) {
  if (String(e.message).includes("Missing perspective-client.wasm")) {
    await perspective.init_client(fetch("perspective-client.wasm"));
    worker = perspective.worker();
  } else throw e;
}

Prevention

When it happens

Trigger: Calling `perspective.worker()`, `perspective.websocket(url)`, or `createMessageHandler()` in a page where `init_client(...)` was never called and no `<perspective-viewer>` element is registered. Also when the viewer custom element has not been upgraded/imported at the time of the call.

Common situations: Bundlers not wiring the default wasm import (tree-shaken or misconfigured wasm plugin); calling `perspective.worker()` at module top level before init code runs; forgetting to import the perspective-viewer package in apps that only use the client API; upgrading to a version where implicit wasm loading was removed in favor of explicit `init_client()`.

Related errors


AI-assisted analysis of perspective-dev/perspective@11c8238c0c (2026-09-09). Data as JSON: /api/errors/c0fa73e9d16e9adf. Report an issue: GitHub.

Appendix: source

Thrown at rust/perspective-js/src/ts/perspective.browser.ts:285

    } else if (wasm instanceof Object) {
        GLOBAL_CLIENT_WASM = Promise.resolve(wasm as typeof psp);
    }
}

function get_client() {
    const viewer_class: any = customElements.get("perspective-viewer");
    if (viewer_class) {
        GLOBAL_CLIENT_WASM = Promise.resolve(viewer_class.__wasm_module__);
        if (
            GLOBAL_CLIENT_MODULE === undefined &&
            viewer_class.__wasm_client_module__
        ) {
            GLOBAL_CLIENT_MODULE = Promise.resolve(
                viewer_class.__wasm_client_module__,
            );
        }
    } else if (GLOBAL_CLIENT_WASM === undefined) {
        throw new Error("Missing perspective-client.wasm");
    }

    return GLOBAL_CLIENT_WASM;
}

/**
 * Returns the compiled `WebAssembly.Module` for the perspective-js client
 * runtime. The module is structured-cloneable, so it can be sent via
 * `postMessage` to a Worker which can instantiate its own `Client` without
 * re-fetching or re-compiling the wasm binary.
 *
 * Requires that the client wasm has been initialized — typically by a prior
 * call to `init_client(...)`, or implicitly by mounting a `<perspective-viewer>`
 * element. Throws otherwise.
 *
 * # Examples
 *
 * ```javascript

View on GitHub (pinned to 11c8238c0c)