perspective-dev/perspective · error · Error
Missing perspective-client.wasm
Error message
Missing perspective-client.wasm
What it means
The DuckDBServer virtual server requires the perspective WASM client module (perspective-client.wasm) to execute DuckDB in WebAssembly. The constructor retrieves the module from the registered `<perspective-viewer>` custom element's `__wasm_module__` property. If the element is registered but the module was never attached, the constructor throws this error.
Solutions
- Import and fully initialize @finos/perspective-viewer (await its init/load of perspective-client.wasm) before constructing DuckDBServer.
- Align versions of @finos/perspective-viewer and perspective-js (same release) and reinstall node_modules.
- Manually fetch perspective-client.wasm and set it on the viewer class: `customElements.get("perspective-viewer").__wasm_module__ = mod;`.
- Confirm your bundler (webpack/vite) is configured to emit and load the .wasm asset so viewer init actually completes.
Example fix
// before
const server = new DuckDBServer(db); // viewer registered but wasm never attached
// after
await import("@finos/perspective-viewer");
await customElements.whenDefined("perspective-viewer");
if (!customElements.get("perspective-viewer").__wasm_module__) {
const mod = await WebAssembly.compileStreaming(fetch("perspective-client.wasm"));
customElements.get("perspective-viewer").__wasm_module__ = mod;
}
const server = new DuckDBServer(db); Defensive patterns
Strategy: validation
Validate before calling
async function ensureDuckDBServerReady() {
await customElements.whenDefined("perspective-viewer");
const viewer = customElements.get("perspective-viewer");
if (!viewer || !viewer.__wasm_module__) {
throw new Error("perspective WASM not attached; await viewer init first");
}
} Type guard
function viewerHasWasm(el: unknown): el is (new () => HTMLElement) & { __wasm_module__: WebAssembly.Module } {
return typeof el === 'function' && (el as any).__wasm_module__ != null;
} Try / catch
try {
const server = new DuckDBServer(db);
} catch (e) {
if (e.message === "Missing perspective-client.wasm") {
await loadPerspectiveViewerWasm();
const server = new DuckDBServer(db); // retry once after init
} else throw e;
} Prevention
- Initialize the perspective-viewer component (which fetches perspective-client.wasm) before any DuckDBServer construction.
- Pin matching versions of perspective packages and verify WASM assets in your bundler output.
- In tests, register the real viewer element, not a stub, or bypass the customElements path.
When it happens
Trigger: Constructing a DuckDBServer while `customElements` is defined, `customElements.get("perspective-viewer")` resolves to a registered class lacking `__wasm_module__` — the viewer web component was registered without its WASM payload being fetched/initialized.
Common situations: Registering the viewer component without awaiting its WASM init; version mismatch between @finos/perspective-viewer and perspective-js so `__wasm_module__` is never set; running under a test harness or polyfill that registers a placeholder `perspective-viewer` element; bundler config stripping the WASM asset so initialization silently no-ops.
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/81eac7eb7956c7d7.
Report an issue: GitHub.
Appendix: source
Thrown at rust/perspective-js/src/ts/virtual_servers/duckdb.ts:278
throw error;
}
}
/**
* An implementation of Perspective's Virtual Server for `@duckdb/duckdb-wasm`.
*/
export class DuckDBHandler implements perspective.VirtualServerHandler {
private db: duckdb.AsyncDuckDBConnection;
private sqlBuilder: perspective.GenericSQLVirtualServerModel;
constructor(db: duckdb.AsyncDuckDBConnection, 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({
column_separator: "|",
like_escape_clause: "\\",
regex_fn: "regexp_matches",
});
}
getFeatures(): perspective.Features {
return {
group_by: true,
split_by: true,
sort: true,View on GitHub (pinned to 11c8238c0c)