schollz/croc · error · Error
croc WASM did not initialize
Error message
croc WASM did not initialize
What it means
The worker instantiated the Go wasm module and called go.run(instance), then polled self.crocWasm for up to 1000ms (100 attempts x 10ms). If the Go runtime never registers the global crocWasm object within that window, initialization is declared failed. This is a readiness-timeout, not proof the wasm is broken: slow devices, main-thread contention, or a panic inside Go's init path can all exceed the 1-second budget.
Source
Thrown at web/public/croc-worker.js:21
let ready;
function initialize() {
if (ready) return ready;
ready = (async () => {
importScripts(new URL("./wasm_exec.js", self.location.href).href);
const go = new Go();
const response = await fetch(new URL("./croc.wasm", self.location.href));
if (!response.ok) {
throw new Error(`Could not load croc.wasm (${response.status})`);
}
const bytes = await response.arrayBuffer();
const { instance } = await WebAssembly.instantiate(bytes, go.importObject);
void go.run(instance);
for (let attempts = 0; !self.crocWasm && attempts < 100; attempts += 1) {
await new Promise((resolve) => setTimeout(resolve, 10));
}
if (!self.crocWasm) {
throw new Error("croc WASM did not initialize");
}
})();
return ready;
}
function transferables(value, output = []) {
if (value instanceof Uint8Array) {
output.push(value.buffer);
} else if (value && typeof value === "object") {
for (const child of Object.values(value)) transferables(child, output);
}
return output;
}
self.addEventListener("message", async (event) => {
const { id, method, args = [] } = event.data;
try {
await initialize();View on GitHub (pinned to e25f1bdc04)
Solutions
- Reproduce with devtools: check the worker console for a Go panic that explains why crocWasm was never registered
- Regenerate croc.wasm and wasm_exec.js from the same Go toolchain so their ABI matches
- If startup is just slow, raise the poll budget (more attempts or longer interval) before giving up
- Reload the page / recreate the worker to rule out a one-off scheduling stall
Example fix
// before (croc-worker.js)
for (let attempts = 0; !self.crocWasm && attempts < 100; attempts += 1) {
await new Promise((resolve) => setTimeout(resolve, 10));
}
// after: allow up to ~15s for slow devices
for (let attempts = 0; !self.crocWasm && attempts < 1500; attempts += 1) {
await new Promise((resolve) => setTimeout(resolve, 10));
} Defensive patterns
Strategy: retry
Try / catch
// Worker startup: terminate and respawn the worker once on init timeout
try {
await rpc.call("ping");
} catch (e) {
if (e.message === "croc WASM did not initialize" && !retriedOnce) {
worker.terminate();
spawnWorker();
retriedOnce = true;
return retry();
}
throw e;
} Prevention
- Rebuild croc.wasm and wasm_exec.js from the same Go version
- Keep the poll budget generous (slow devices) — e.g. several seconds, not 1s
- Watch the worker console for Go panics during init; treat those as build bugs, not timeouts
When it happens
Trigger: Running on low-powered hardware or under heavy CPU throttling where Go's runtime startup plus package init takes longer than 1s; a Go-side panic during initialization that silently prevents crocWasm from being set; wasm_exec.js version mismatch with the compiled croc.wasm so go.run never completes.
Common situations: First load on mobile browsers with cold caches; CI headless-browser tests under CPU throttling; rebuilding croc.wasm with a different Go version without updating wasm_exec.js.
Related errors
AI-assisted analysis of schollz/croc@e25f1bdc04 (2026-08-15).
Data as JSON: /api/errors/0e6f591594d0ce71.
Report an issue: GitHub.