swc-project/swc · critical
Should able to read memory from given ptr
Error message
Should able to read memory from given ptr
What it means
Thrown by swc_plugin_runner when the host side of the SWC wasm-plugin bridge copies bytes out of the plugin's linear memory: caller.read_buf(bytes_ptr, buf) failed for the (ptr, len) pair the plugin passed to a host-imported function. It means the pointer range is outside the plugin guest's current memory bounds, or points at stale/freed memory. This is a Rust panic (expect), so it aborts the embedding process unless caught.
Source
Thrown at crates/swc_plugin_runner/src/memory_interop.rs:16
use swc_common::plugin::serialized::PluginSerializedBytes;
use crate::runtime;
#[cfg_attr(debug_assertions, tracing::instrument(level = "info", skip_all))]
pub fn copy_bytes_into_host(
caller: &dyn runtime::Caller<'_>,
bytes_ptr: i32,
bytes_ptr_len: i32,
buf: &mut Vec<u8>,
) {
let len: usize = bytes_ptr_len.try_into().unwrap();
buf.resize(len, 0);
caller
.read_buf(bytes_ptr as u32, buf)
.expect("Should able to read memory from given ptr");
}
/// Locate a view from given memory, write serialized bytes into.
#[cfg_attr(debug_assertions, tracing::instrument(level = "info", skip_all))]
pub fn write_into_memory_view<F>(
view: &mut dyn runtime::Caller<'_>,
serialized_bytes: &PluginSerializedBytes,
get_allocated_ptr: F,
) -> (u32, u32)
where
F: Fn(&mut dyn runtime::Caller<'_>, usize) -> u32,
{
let serialized_len = serialized_bytes.as_slice().len();
let ptr_start = get_allocated_ptr(view, serialized_len);
let serialized_size = serialized_len
.try_into()
.expect("Should be able to convert to i32");View on GitHub (pinned to 5176682b65)
Solutions
- Rebuild the plugin against the exact swc_core version required by the swc/@swc/core version you run (check the plugin's compatibility table) and target wasm32-wasi.
- Upgrade or pin the host (swc crate or @swc/core npm package) to the version matching the plugin.
- Reproduce with debug_assertions enabled to get the tracing spans (copy_bytes_into_host is instrumented) showing which host import received the bad pointer.
- Isolate plugin transforms with std::panic::catch_unwind or a subprocess/worker so a buggy plugin cannot abort the whole build.
Example fix
// before: plugin panic kills the whole compiler process
let out = compiler.process_js_file(&fm, &handler, &config)?;
// after: isolate plugin-bearing transforms and degrade gracefully
let out = match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
compiler.process_js_file(&fm, &handler, &config)
})) {
Ok(Ok(res)) => res,
Ok(Err(e)) => return Err(e),
Err(payload) => {
tracing::error!(?payload, "swc plugin passed a bad ptr; retrying without plugins");
let cfg_no_plugins = strip_plugins(config);
compiler.process_js_file(&fm, &handler, &cfg_no_plugins)?
}
}; Defensive patterns
Strategy: try-catch
Try / catch
// The failure is a host-side panic, so the only catch site is catch_unwind
// (or a subprocess). Isolate every plugin-bearing transform.
use std::panic::{catch_unwind, AssertUnwindSafe};
fn run_with_plugins<T>(f: impl FnOnce() -> anyhow::Result<T>) -> anyhow::Result<T> {
match catch_unwind(AssertUnwindSafe(f)) {
Ok(res) => res,
Err(payload) => {
let msg = payload
.downcast_ref::<&str>()
.map(|s| s.to_string())
.or_else(|| payload.downcast_ref::<String>().cloned())
.unwrap_or_else(|| "unknown plugin panic".into());
anyhow::bail!("swc plugin panicked: {msg}")
}
}
} Prevention
- Keep the plugin's swc_core version identical to the swc/@swc/core version executing it; check the plugin README compatibility table on every upgrade.
- Build plugins with the official swc_plugin macro targeting wasm32-wasi in release mode; never mix debug/release or custom allocators.
- Do not build with panic=abort if you rely on catch_unwind isolation; prefer a worker subprocess for full isolation.
- Smoke-test each plugin on small inputs in CI before large production files hit it.
When it happens
Trigger: A plugin calls a host import that takes (ptr, len) arguments (transform result retrieval, comments proxy, source-map proxy, diagnostics) with a pointer that was freed, was computed before a memory.grow, or exceeds the wasm memory size; also when the plugin binary's ABI does not match the host runtime.
Common situations: Plugin compiled with a swc_core version that does not match the host swc version (schema/ABI drift); plugin built for the wrong wasm target; plugin panicking or corrupting its own allocator mid-transform; extremely large serialized payloads overflowing the guest heap.
Related errors
- Should able to write into memory view
- Should able to be deserialized into string
- Should be serializable
- Should be serializable
- Should able to deserialize
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/4f6f5591b9b3cf4a.
Report an issue: GitHub.