perspective-dev/perspective · error · Error

Failed to fetch perspective server wasm

Error message

Failed to fetch perspective server wasm (HTTP ${wasm.status} "${wasm.url}")

What it means

materialize_server_wasm accepts a Response (or bytes) representing the perspective server wasm. When given a Response whose ok flag is false (non-2xx HTTP status — 404, 500, CORS-failed fetch surfaced as an error page, etc.), it throws this Error naming the HTTP status and URL. The library does this because an unsuccessful fetch cannot yield valid wasm bytes to instantiate.

Solutions

  1. Open the ${wasm.url} from the message in a browser/curl and fix the 404/5xx — usually a wrong base URL or missing asset in the deployment.
  2. Serve the wasm file at the expected path with the correct version matching the perspective-js package.
  3. Check CORS and authentication: the wasm endpoint must be reachable cross-origin (Access-Control-Allow-Origin) and not blocked by auth middleware.
  4. If you pre-fetch the Response yourself, check resp.ok and surface a clearer error before passing it on.
  5. Pin/align versions of the server wasm and the JS client so the URL built by select_server_wasm matches what's deployed.

Example fix

// before
const resp = await fetch(wasmUrl);
await engine.materialize_server_wasm(resp);
// after: guard before handing off
const resp = await fetch(wasmUrl);
if (!resp.ok) throw new Error(`Cannot load wasm: HTTP ${resp.status} for ${wasmUrl}`);
await engine.materialize_server_wasm(resp);
Defensive patterns

Strategy: try-catch

Validate before calling

async function fetchWasmOrThrow(url: string): Promise<Response> {
  const resp = await fetch(url);
  if (!resp.ok) throw new Error(`Cannot load perspective wasm: HTTP ${resp.status} for ${url}`);
  return resp;
}

Type guard

function isOkWasmResponse(wasm: unknown): wasm is Response {
  return typeof Response !== "undefined" && wasm instanceof Response && wasm.ok;
}

Try / catch

try {
  await engine.materialize_server_wasm(resp);
} catch (e) {
  if (e instanceof Error && e.message.startsWith("Failed to fetch perspective server wasm")) {
    console.error("Perspective wasm fetch failed:", e.message);
    resp = await fetchWithRetry(altWasmUrl, 3);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the API with a Response for the perspective server wasm where wasm.ok is false — i.e. the fetch returned 404/403/500/etc. materialize_server_wasm is reached via select_server_wasm when the caller supplies a pre-fetched Response instead of a URL or Uint8Array.

Common situations: Wrong or outdated CDN/base URL so the .wasm path 404s; server not serving the wasm with correct MIME/route; deployment where the wasm asset was renamed or versioned; CORS or auth middleware returning 401/403; reverse proxy returning 502 during deploys.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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

Appendix: source

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

        (typeof Response !== "undefined" && wasm instanceof Response) ||
        wasm instanceof Promise ||
        wasm instanceof WebAssembly.Module ||
        typeof wasm === "function"
    );
}

async function materialize_server_wasm(
    source: ServerWasmSource,
    disable_stage_0: boolean,
): Promise<ArrayBuffer | WebAssembly.Module> {
    let wasm = typeof source === "function" ? await source() : await source;
    if (wasm instanceof Uint8Array) {
        wasm = wasm.buffer as ArrayBuffer;
    }

    if (typeof Response !== "undefined" && wasm instanceof Response) {
        if (!wasm.ok) {
            throw new Error(
                `Failed to fetch perspective server wasm (HTTP ${wasm.status} "${wasm.url}")`,
            );
        }

        if (disable_stage_0) {
            return await wasm.arrayBuffer();
        }
    }

    if (disable_stage_0) {
        return wasm as ArrayBuffer | WebAssembly.Module;
    }

    const bytes = await load_wasm_stage_0(wasm);
    return bytes.buffer as ArrayBuffer;
}

async function select_server_wasm(

View on GitHub (pinned to 11c8238c0c)