perspective-dev/perspective · error · Error

Missing perspective-client.wasm

Error message

Missing perspective-client.wasm

What it means

The ClickHouseServer virtual server needs the perspective WebAssembly client module (perspective-client.wasm) to run the database engine in-process. It expects the WASM module to be attached to the registered `<perspective-viewer>` custom element via its `__wasm_module__` property. If the custom element is registered but does not carry the module, the constructor throws this error rather than running without WASM support.

Solutions

  1. Ensure @finos/perspective-viewer (and its WASM assets) are fully imported and initialized before creating the ClickHouseServer, so its `__wasm_module__` is set.
  2. Verify the installed @finos/perspective-viewer version matches the perspective-js package version; upgrade/reinstall matching versions.
  3. If not using the viewer component, explicitly fetch perspective-client.wasm and assign it to the viewer class's `__wasm_module__` before constructing the server.
  4. Check that no custom/stub `perspective-viewer` element is registered in `customElements` shadowing the real one.

Example fix

// before
import "@finos/perspective-viewer"; // component registered, wasm not yet loaded
const server = new ClickHouseServer(db);

// after
import perspectiveViewer from "@finos/perspective-viewer";
await perspectiveViewer.init?.(); // ensures perspective-client.wasm is attached as __wasm_module__
const server = new ClickHouseServer(db);
Defensive patterns

Strategy: validation

Validate before calling

function canCreateClickHouseServer() {
  const viewer = typeof customElements !== "undefined" && customElements.get("perspective-viewer");
  return Boolean(viewer && viewer.__wasm_module__);
}
if (!canCreateClickHouseServer()) throw new Error("perspective-viewer WASM module not loaded yet");

Type guard

function hasWasmModule(el): el is (typeof el & { __wasm_module__: WebAssembly.Module }) {
  return typeof el === 'function' && '__wasm_module__' in el && el.__wasm_module__ != null;
}

Try / catch

try {
  const server = new ClickHouseServer(db);
} catch (e) {
  if (e.message === "Missing perspective-client.wasm") {
    await initPerspectiveViewer(); // load/attach wasm, then retry
  } else throw e;
}

Prevention

When it happens

Trigger: Constructing a ClickHouseServer when `customElements` is available, `customElements.get("perspective-viewer")` returns a registered class, but that class has no `__wasm_module__` property — i.e. the perspective-viewer web component was registered without its WASM assets being loaded/initialized first.

Common situations: Loading only the viewer CSS/tag without calling the viewer's init (which fetches and attaches perspective-client.wasm); importing a stub or older/mismatched @finos/perspective-viewer version that doesn't set __wasm_module__; using a custom element registry (e.g. Shadow DOM scoped or overridden registry) where a proxy viewer class is registered; attempting to use the virtual server outside a browser environment or before the WASM bundle finished loading.

Related errors


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

Appendix: source

Thrown at rust/perspective-js/src/ts/virtual_servers/clickhouse.ts:263

        release();
    }
}

/**
 * An implementation of Perspective's Virtual Server for `@duckdb/duckdb-wasm`.
 */
export class ClickhouseHandler implements perspective.VirtualServerHandler {
    private db: clickhouse.ClickHouseClient;
    private sqlBuilder: perspective.GenericSQLVirtualServerModel;
    constructor(db: clickhouse.ClickHouseClient, mod?: typeof perspective) {
        if (!mod) {
            if (customElements) {
                const viewer_class: any =
                    customElements.get("perspective-viewer");
                if (viewer_class) {
                    mod = viewer_class.__wasm_module__;
                } else {
                    throw new Error("Missing perspective-client.wasm");
                }
            } else {
            }
        }

        this.db = db;
        this.sqlBuilder = new mod!.GenericSQLVirtualServerModel({
            create_entity: "VIEW",
            grouping_fn: "GROUPING",
            column_separator: "|",
            backslash_escaped_literals: true,
            regex_fn: "match",
        });
    }

    getFeatures(): perspective.Features {
        return {
            group_by: true,

View on GitHub (pinned to 11c8238c0c)