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
- Ensure @finos/perspective-viewer (and its WASM assets) are fully imported and initialized before creating the ClickHouseServer, so its `__wasm_module__` is set.
- Verify the installed @finos/perspective-viewer version matches the perspective-js package version; upgrade/reinstall matching versions.
- 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.
- 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
- Always import and await perspective-viewer's initialization before instantiating virtual servers.
- Keep @finos/perspective-viewer and perspective-js on the same version.
- Add an app-startup assertion that `customElements.get('perspective-viewer').__wasm_module__` exists.
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
- Missing perspective-client.wasm
- Init error
- init_server requires a wasm source or a
- Missing perspective-client.wasm
- Missing perspective-server.wasm
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)