{"record":{"id":"34ae6d7da32a8e28","repo":"tursodatabase/turso","slug":"panic-mainworker-is-not-initialized","errorCode":null,"errorMessage":"panic: MainWorker is not initialized","messagePattern":"panic: MainWorker is not initialized","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"bindings/javascript/packages/wasm/promise-bundle.ts","lineNumber":8,"sourceCode":"import { DatabasePromise, DatabaseOpts, SqliteError, Transaction } from \"@tursodatabase/database-common\"\nimport { registerFileAtWorker, unregisterFileAtWorker, ioNotifier } from \"@tursodatabase/database-wasm-common\";\nimport { initThreadPool, MainWorker, Database as NativeDatabase } from \"./index-bundle.js\";\n\nasync function init(): Promise<Worker> {\n    await initThreadPool();\n    if (MainWorker == null) {\n        throw new Error(\"panic: MainWorker is not initialized\");\n    }\n    return MainWorker;\n}\n\nclass Database extends DatabasePromise {\n    #worker: Worker | null;\n    constructor(path: string, opts: DatabaseOpts = {}) {\n        super(\n            new NativeDatabase(path, opts) as unknown as any,\n            () => ioNotifier.waitForCompletion(),\n        )\n    }\n    /**\n     * connect database and pre-open necessary files in the OPFS\n     */\n    override async connect() {\n        if (!this.memory) {\n            const worker = await init();","sourceCodeStart":1,"sourceCodeEnd":26,"githubUrl":"https://github.com/tursodatabase/turso/blob/244cde92a7df7f9b8b8b7a4075c35a12977e303e/bindings/javascript/packages/wasm/promise-bundle.ts#L1-L26","documentation":"The bundle-variant WASM promise entry (promise-bundle.ts:8) defines init(): it awaits initThreadPool() and then requires the live-exported MainWorker from index-bundle.js to be non-null. MainWorker is assigned inside the setupMainThread callback in index-bundle.ts when the worker is created; if it is still null after initThreadPool(), the worker was never registered in this module instance. The classic cause is the bundler creating two copies of the wasm module (only the copy that ran setupMainThread got the worker) or picking an entry variant your bundler does not support.","triggerScenarios":"Importing the database from one module instance while another duplicate copy (created by bundler resolution) ran setupMainThread; mixing entry files (index-bundle.js, index-default.js, hack variants) in one app; calling Database before the module's top-level await (fetch of turso.wasm + setupMainThread) completed in the copy you imported; worker script failing to load so the callback never assigned MainWorker.","commonSituations":"Webpack/rollup-style setups where '#index' or subpath imports resolve to two physical files; monorepos with duplicate @tursodatabase/database-wasm versions; SSR frameworks evaluating the module on the server where Worker is unavailable; using the bundle variant with a bundler that needs the vite/turbopack hack variant instead.","solutions":["Import Database and everything else from exactly one entry point of one package copy (dedupe @tursodatabase/database-wasm in the lockfile).","Call and await the entry's init() once at startup before constructing any Database.","Pick the entry variant matching your bundler (e.g. promise-vite-dev-hack under Vite dev, promise-turbopack-hack under Turbopack) instead of mixing them.","Ensure the worker and turso.wasm assets are served (check network tab) so setupMainThread can create the worker.","Keep the module out of SSR main builds (load it lazily in the browser only)."],"exampleFix":"// before\nimport { Database } from \"@tursodatabase/database-wasm/promise-bundle\";\nconst db = new Database(\"app.db\"); // module copy never initialized MainWorker\n\n// after\nimport { init, Database } from \"@tursodatabase/database-wasm/promise-bundle\";\nawait init(); // worker registered in THIS module instance\nconst db = new Database(\"app.db\");","handlingStrategy":"validation","validationCode":"import { init, Database } from \"@tursodatabase/database-wasm/promise-bundle\";\nlet ready: Promise<Worker> | null = null;\nexport function ensureInit() {\n  return (ready ??= init()); // single, awaited initialization\n}\n// app startup: await ensureInit(); before any new Database(...)","typeGuard":null,"tryCatchPattern":"try {\n  await init();\n} catch (e) {\n  if (e instanceof Error && /MainWorker is not initialized/.test(e.message)) {\n    // module duplication or failed worker spawn: dedupe entries / check network for worker.js + turso.wasm\n  } else throw e;\n}","preventionTips":["Import Database from exactly one entry variant of one package copy.","Await init() once at startup; cache the promise.","Verify worker.js and turso.wasm assets load (network tab) after bundling.","Keep the module out of SSR builds; load it lazily in the browser."],"tags":["wasm","initialization","worker","webpack","module-duplication"],"backgroundTag":"module-not-initialized","analyzedSha":"244cde92a7df7f9b8b8b7a4075c35a12977e303e","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}