denoland/deno · critical

Bootstrap exception: {error}

Error message

Bootstrap exception: {error}

What it means

After the runtime is created, MainWorker::bootstrap invokes the cached bootstrap main function (99_main.js) with the bootstrap options. If that call throws a JS exception, it is converted via JsError::from_v8_exception and re-raised as a Rust panic, because a runtime that fails bootstrap cannot serve anything.

Source

Thrown at runtime/worker.rs:851

    {
      let op_state = self.js_runtime.op_state();
      let mut state = op_state.borrow_mut();
      state.put(options.clone());
      if let Some((fd, serialization)) = options.node_ipc_init {
        state.put(deno_node::ChildPipeFd(fd, serialization));
      }
    }

    deno_core::scope!(scope, &mut self.js_runtime);
    v8::tc_scope!(scope, scope);
    let args = options.as_v8(scope);
    let bootstrap_fn = self.bootstrap_fn_global.take().unwrap();
    let bootstrap_fn = v8::Local::new(scope, bootstrap_fn);
    let undefined = v8::undefined(scope);
    bootstrap_fn.call(scope, undefined.into(), &[args]);
    if let Some(exception) = scope.exception() {
      let error = JsError::from_v8_exception(scope, exception);
      panic!("Bootstrap exception: {error}");
    }
    if let Some(t) = t0 {
      #[allow(clippy::print_stderr, reason = "diagnostic")]
      {
        eprintln!(
          "[startup] {:>32}  {:?}",
          "MainWorker::bootstrap (99_main)",
          t.elapsed()
        );
      }
    }
  }

  #[cfg(not(target_os = "linux"))]
  pub fn setup_memory_trim_handler(&mut self) {
    // Noop
  }

View on GitHub (pinned to a961cdec3b)

Solutions

  1. Rebuild startup snapshots after upgrading Deno crates so snapshot JS matches Rust ops
  2. Do not set skip_op_registration unless you re-register every op the snapshot JS calls
  3. Read the {error} text - it is the JS exception from 99_main.js (missing op, undefined function, etc.) and names the failing step
  4. Reproduce with a minimal extension set to identify which extension's JS fails
Defensive patterns

Strategy: validation

Try / catch

// Embedders can isolate bootstrap failures at startup
let boot = std::panic::catch_unwind(AssertUnwindSafe(|| worker.bootstrap(options)));
if boot.is_err() {
  // snapshot/op mismatch: rebuild the snapshot before retrying, do not serve traffic
}

Prevention

When it happens

Trigger: JS code in the bootstrap chain throwing: a startup snapshot that mismatches the Rust ops (e.g. skip_op_registration set without re-registering ops), a corrupted snapshot blob from a partial build, or embedder bootstrap options that violate invariants.

Common situations: Embedders building custom snapshots and workers; upgrading deno_core/deno_runtime while reusing an old snapshot; enabling skip_op_registration without supplying all ops.

Related errors


AI-assisted analysis of denoland/deno@a961cdec3b (2026-08-20). Data as JSON: /api/errors/eca03433730946e6. Report an issue: GitHub.