{"record":{"id":"8898e4c02193c73c","repo":"denoland/deno","slug":"web-workers-are-not-supported","errorCode":null,"errorMessage":"web workers are not supported","messagePattern":"web workers are not supported","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"runtime/worker.rs","lineNumber":322,"sourceCode":"  // user code.\n  pub should_wait_for_inspector_session: bool,\n  /// If Some, print a low-level trace output for ops matching the given patterns.\n  pub trace_ops: Option<Vec<String>>,\n\n  pub cache_storage_dir: Option<std::path::PathBuf>,\n  pub origin_storage_dir: Option<std::path::PathBuf>,\n  pub stdio: Stdio,\n  pub enable_raw_imports: bool,\n  pub enable_stack_trace_arg_in_ops: bool,\n\n  pub unconfigured_runtime: Option<UnconfiguredRuntime>,\n}\n\nimpl Default for WorkerOptions {\n  fn default() -> Self {\n    Self {\n      create_web_worker_cb: Arc::new(|_| {\n        unimplemented!(\"web workers are not supported\")\n      }),\n      skip_op_registration: false,\n      seed: None,\n      unsafely_ignore_certificate_errors: Default::default(),\n      should_break_on_first_statement: Default::default(),\n      should_wait_for_inspector_session: Default::default(),\n      trace_ops: Default::default(),\n      format_js_error_fn: Default::default(),\n      origin_storage_dir: Default::default(),\n      cache_storage_dir: Default::default(),\n      extensions: Default::default(),\n      startup_snapshot: Default::default(),\n      residual_lazy_js_sources: &[],\n      residual_lazy_esm_sources: &[],\n      create_params: Default::default(),\n      bootstrap: Default::default(),\n      stdio: Default::default(),\n      enable_raw_imports: false,","sourceCodeStart":304,"sourceCodeEnd":340,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/runtime/worker.rs#L304-L340","documentation":"runtime/worker.rs:322 is the default create_web_worker_cb inside WorkerOptions::default(); it is an unimplemented!() panic that fires only if a runtime embedder never supplied a real web-worker factory. The Deno CLI always overrides this callback, so end users should never see it — seeing it means a custom deno_runtime/deno_core integration started a JS Worker (new Worker(...)) without wiring nested-worker creation.","triggerScenarios":"Embedding deno_runtime with WorkerOptions::default() (or any Options struct where create_web_worker_cb was never set) and then executing JavaScript that calls new Worker(new URL(\"./w.js\", import.meta.url), { type: \"module\" }) or new SharedWorker.","commonSituations":"Building custom runtimes/sandboxes on deno_core+deno_runtime (server-side scripting hosts, plugin systems, edge platforms); copying a minimal deno_runtime example that predates the callback being required; upgrading deno_runtime versions where defaults became stricter about nested workers.","solutions":["Provide a real create_web_worker_cb when constructing WorkerOptions (Arc<dyn Fn(WebWorkerOptions) -> Result<WebWorker>>), typically reusing deno_runtime::worker::create_web_worker_init_cb and re-registering your extensions","Decide the embedding policy: disable worker creation entirely by erroring deliberately in the callback instead of leaving the unimplemented!() default","If you intended the Deno CLI behavior, run scripts through the deno binary rather than a hand-rolled runtime bootstrap"],"exampleFix":"// before (Rust embedder)\nlet options = WorkerOptions::default(); // create_web_worker_cb = unimplemented!\n\n// after\nlet options = WorkerOptions {\n  create_web_worker_cb: Arc::new(|init| {\n    Ok(deno_runtime::worker::WebWorker::bootstrap_from_options(\n      init.main_module,\n      deno_runtime::worker::WebWorkerOptions { /* extensions, perms, ... */ ..init },\n    ))\n  }),\n  ..Default::default()\n};","handlingStrategy":"validation","validationCode":"// Rust, before creating the runtime\nfn assert_workers_supported(options: &WorkerOptions) -> Result<(), String> {\n    let ok = matches!(\n        std::thread::catch_unwind(std::panic::AssertUnwindSafe(|| {\n            // probing is unsafe; instead track whether the cb was set by construction\n            false\n        })),\n        _ => false\n    );\n    let _ = ok;\n    // Practical check: gate on your own builder flag\n    if !options.extensions.is_empty() /* proxy for custom bootstrap */ {\n        Ok(())\n    } else {\n        Err(\"create_web_worker_cb not supplied\".into())\n    }\n}","typeGuard":null,"tryCatchPattern":"// JS side: you cannot catch a Rust unimplemented!() panic — prevent it in the embedder instead.\n// Rust embedder: wrap runtime execution in catch_unwind to log which feature requested a Worker.\nlet result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    rt.block_on(main_js_future)\n}));\nif result.is_err() { /* log 'web workers requested but unsupported' */ }","preventionTips":["Never ship WorkerOptions::default() to production; always set create_web_worker_cb explicitly","Make worker support a documented capability flag of your embedding and test new Worker(...) in your test suite","Alternatively deliberately return an error from the callback so JS gets a catchable failure instead of a panic"],"tags":["runtime","workers","embedder","panic"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}