tursodatabase/turso · error · Error

panic: MainWorker is not initialized

Error message

panic: MainWorker is not initialized

What it means

The default WASM promise entry (promise-default.ts:8) throws this from init() when MainWorker - a live export of index-default.ts assigned inside the setupMainThread callback - is still null after initThreadPool() resolves. index-default.ts uses top-level await (fetches turso.wasm, then setupMainThread spawns the 'turso-database' module worker), so a null MainWorker means the worker-creation callback never ran for the module instance you imported: either a duplicate module copy, an unloaded worker/wasm asset, or calling into the module before its top-level await chain finished.

Source

Thrown at bindings/javascript/packages/wasm/promise-default.ts:8

import { DatabasePromise, DatabaseOpts, SqliteError, Transaction } from "@tursodatabase/database-common"
import { registerFileAtWorker, unregisterFileAtWorker, ioNotifier } from "@tursodatabase/database-wasm-common";
import { initThreadPool, MainWorker, Database as NativeDatabase } from "./index-default.js";

async function init(): Promise<Worker> {
    await initThreadPool();
    if (MainWorker == null) {
        throw new Error("panic: MainWorker is not initialized");
    }
    return MainWorker;
}

class Database extends DatabasePromise {
    #worker: Worker | null;
    constructor(path: string, opts: DatabaseOpts = {}) {
        const nativeDb = new NativeDatabase(path, opts);
        super(
            nativeDb as unknown as any,
            // In-memory databases use MemoryIO which completes I/O synchronously,
            // so there's no OPFS Worker dispatch and the IONotifier would never fire.
            // Use undefined (defaults to no-op) so the step loop retries immediately.
            (nativeDb as any).memory ? undefined : () => ioNotifier.waitForCompletion(),
        )
    }
    /**
     * connect database and pre-open necessary files in the OPFS

View on GitHub (pinned to 244cde92a7)

Solutions

  1. Await init() from the same entry module before any Database construction.
  2. Verify turso.wasm32-wasi.wasm and worker.js are fetched successfully (network tab) and match the import base.
  3. Dedupe the package so a single index-default.js instance exists (check the bundler's module graph / lockfile duplicates).
  4. Load the wasm entry lazily and only in the browser (dynamic import inside useEffect/onMount), never during SSR.

Example fix

// before
import { Database } from "@tursodatabase/database-wasm/promise-default";
export const db = new Database("app.db"); // module-level, init not awaited

// after
import { init, Database } from "@tursodatabase/database-wasm/promise-default";
export async function openDb() {
  await init();
  return new Database("app.db");
}
Defensive patterns

Strategy: validation

Validate before calling

import { init, Database } from "@tursodatabase/database-wasm/promise-default";
export async function openDb(path: string) {
  await init(); // resolves only after MainWorker exists
  return new Database(path);
}

Try / catch

try {
  await init();
} catch (e) {
  if (e instanceof Error && /MainWorker is not initialized/.test(e.message)) {
    // check for duplicate module copies and 404s on turso.wasm32-wasi.wasm / worker.js
  } else throw e;
}

Prevention

When it happens

Trigger: Bundler resolving @tursodatabase/database-wasm/promise-default and other deep imports to different physical copies of index-default.js; the browser failing to fetch ./turso.wasm32-wasi.wasm or ./worker.js (404 from wrong base path after bundling); constructing Database in a module that captured the exports before the top-level await settled; running under SSR/jsdom where Worker is missing so setupMainThread silently never assigned MainWorker.

Common situations: Vite/Next.js dev servers re-optimizing and serving two copies of the wasm package; assets not copied to the dist base path; Node SSR prerender importing the browser entry; ad-blockers or CSP blocking worker creation.

Related errors


AI-assisted analysis of tursodatabase/turso@244cde92a7 (2026-08-20). Data as JSON: /api/errors/b9c088abec8f34d7. Report an issue: GitHub.