denoland/deno · error

Couldn't consume WasmStreamingResource.

Error message

Couldn't consume WasmStreamingResource.

What it means

The abort path of Deno's wasm streaming: when a compilation is aborted, the op takes the WasmStreamingResource out of the resource table and must be its sole owner (Rc::try_unwrap) to call abort() on the underlying stream. If another Rc reference survives, the unwrap fails and the process panics. This is an internal lifecycle invariant; the documented API surface never exposes those references.

Source

Thrown at libs/core/ops_builtin_v8.rs:1464

  state: Rc<RefCell<OpState>>,
  rid: u32,
  error: v8::Local<v8::Value>,
) -> Result<(), ResourceError> {
  // NOTE: v8::WasmStreaming::abort can't be called while `state` is borrowed;
  let wasm_streaming = state
    .borrow_mut()
    .resource_table
    .take::<WasmStreamingResource>(rid)?;

  // At this point there are no clones of Rc<WasmStreamingResource> on the
  // resource table, and no one should own a reference because we're never
  // cloning them. So we can be sure `wasm_streaming` is the only reference.
  match std::rc::Rc::try_unwrap(wasm_streaming) {
    Ok(wsr) => {
      wsr.0.into_inner().abort(Some(error));
    }
    _ => {
      panic!("Couldn't consume WasmStreamingResource.");
    }
  }
  Ok(())
}

// This op calls `op_apply_source_map` re-entrantly.
#[op2(reentrant)]
pub fn op_destructure_error<'s, 'i>(
  scope: &mut v8::PinScope<'s, 'i>,
  error: v8::Local<'s, v8::Value>,
) -> JsError {
  *JsError::from_v8_exception(scope, error)
}

/// Effectively throw an uncatchable error. This will terminate runtime
/// execution before any more JS code can run, except in the REPL where it
/// should just output the error to the console.
#[op2(fast, reentrant)]

View on GitHub (pinned to 336da420f4)

Solutions

  1. Update Deno/deno_core — lifecycle races in the streaming resource are fixed at the core level
  2. Do not touch resource ids for in-flight wasm compilations; let the promise settle
  3. Reproduce minimally (compileStreaming plus a concurrent abort) and report to denoland/deno with the script

Example fix

// before — aborting while manually manipulating the resource id
const p = WebAssembly.compileStreaming(fetch("./mod.wasm"));
Deno.core.close(wasmRid); // during in-flight compilation

// after — only abort via the promise; never touch the rid
const p = WebAssembly.compileStreaming(fetch("./mod.wasm")).catch((e) => {
  console.error("compile aborted:", e);
  return null;
});
Defensive patterns

Strategy: validation

Validate before calling

// let abort flow through the promise; never touch the streaming rid
const mod = await WebAssembly.compileStreaming(fetch("./mod.wasm")).catch((e) => {
  console.error("compile aborted:", e);
  return null;
});

Prevention

When it happens

Trigger: A WebAssembly.compileStreaming promise being aborted or rejected while an extra reference to the streaming resource is alive — resource-table misuse by tooling, or a race between abort and completion inside deno_core. The sibling close() path in ops_builtin.rs has the identical guard.

Common situations: Custom tooling that holds or closes wasm resource ids during an in-flight compilation; races between abort and completion on older deno_core versions; practically unseen in normal CLI usage.

Related errors


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