ruvnet/ruflo · error · Error

Failed to load WASM module

Error message

Failed to load WASM module

What it means

Thrown by initWasmMcp() (browser-only) when loadWasm() resolves to a falsy value, before any MCP server is constructed. The WASM module is expected to expose WasmMcpServer and WasmGallery constructors; a falsy return means the module never loaded or was not the expected export surface.

Source

Thrown at ruflo/src/ruvocal/src/lib/stores/wasmMcp.ts:84

// Request ID counter
let requestId = 0;

/**
 * Initialize the WASM MCP server
 */
export async function initWasmMcp(): Promise<boolean> {
	if (!browser) return false;

	const state = get(wasmMcpState);
	if (state.loaded || state.loading) return state.loaded;

	wasmMcpState.update((s) => ({ ...s, loading: true, error: null }));

	try {
		// Load WASM module
		const wasm = await loadWasm();
		if (!wasm) {
			throw new Error("Failed to load WASM module");
		}

		// Create MCP server and gallery instances
		const mcpServer = new wasm.WasmMcpServer();
		const gallery = new wasm.WasmGallery();

		// Initialize the MCP server
		const initResponse = callMcpInternal(mcpServer, "initialize", {
			protocolVersion: "2024-11-05",
			clientInfo: { name: "ruvocal-ui", version: "1.0.0" },
		});

		if (initResponse.error) {
			throw new Error(`MCP initialization failed: ${initResponse.error.message}`);
		}

		// Load persisted filesystem state from IndexedDB
		await syncFromIndexedDB(mcpServer);

View on GitHub (pinned to 6b01dc5a68)

Solutions

  1. Open the browser devtools Network tab and confirm the .wasm asset loads with 200 and application/wasm.
  2. Check the Console for an instantiation/CSP error that loadWasm() may have caught and converted to a null return.
  3. Verify Content-Security-Policy includes 'wasm-unsafe-eval' (and 'self') for scripts.
  4. Confirm initWasmMcp() is only invoked when `browser` is true and after the component mounted.
  5. Rebuild the WASM package; a stale glue file can export a different shape than loadWasm expects.

Example fix

// before
const wasm = await loadWasm();
if (!wasm) throw new Error("Failed to load WASM module");
// after
const wasm = await loadWasm();
if (!wasm || typeof wasm.WasmMcpServer !== "function") {
  throw new Error(`Failed to load WASM module (exports: ${Object.keys(wasm ?? {}).join(",")})`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

function wasmLikelyAvailable(): boolean {
  return (
    typeof WebAssembly === "object" &&
    typeof WebAssembly.instantiate === "function" &&
    // CSP must allow wasm; not directly testable, but feature-detect compile
    typeof WebAssembly.compile === "function"
  );
}
if (browser && !wasmLikelyAvailable()) {
  console.warn("WebAssembly unavailable; WASM MCP will be disabled");
}

Type guard

interface WasmExports {
  WasmMcpServer: new () => unknown;
  WasmGallery: new () => unknown;
}
function isWasmExports(w: unknown): w is WasmExports {
  return (
    !!w &&
    typeof (w as WasmExports).WasmMcpServer === "function" &&
    typeof (w as WasmExports).WasmGallery === "function"
  );
}

Try / catch

try {
  const ok = await initWasmMcp();
  if (!ok) wasmMcpState.update((s) => ({ ...s, error: "WASM MCP unavailable" }));
} catch (e) {
  wasmMcpState.update((s) => ({ ...s, loaded: false, loading: false, error: String((e as Error)?.message ?? e) }));
}

Prevention

When it happens

Trigger: Calling initWasmMcp() during SSR (the browser guard returns false earlier, so this path is browser-only), the WASM .wasm/.js glue asset 404s or fails to instantiate, the environment lacks WebAssembly support, or loadWasm() swallowed an instantiation error and returned null.

Common situations: Build did not emit the WASM asset to the expected path; CSP blocks wasm-unsafe-eval or the blob/StreamingInstantiate path; an older browser/worker context without WebAssembly; a misconfigured base path so the importer resolves to an HTML 404 page.

Related errors


AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12). Data as JSON: /api/errors/53ff35dcb3707336. Report an issue: GitHub.