swc-project/swc · critical
Should be serializable
Error message
Should be serializable
What it means
Host import that serves a plugin its transform config: it serializes `transform_plugin_config` to a JSON string and then encodes that string as versioned CBOR for the guest; a CBOR encode failure panics. A JSON-unserializable config is already handled gracefully (serde_json error maps to `.ok()` and the host returns 0), so the panic is confined to encoding a plain String - which only fails under host/guest schema divergence or a runner bug.
Source
Thrown at crates/swc_plugin_runner/src/imported_fn/metadata_context.rs:63
let mut buf = env.mutable_context_key_buffer.lock();
copy_bytes_into_host(caller, bytes_ptr, bytes_ptr_len, &mut buf);
}
#[cfg_attr(debug_assertions, tracing::instrument(level = "info", skip_all))]
pub fn get_transform_plugin_config(
caller: &mut dyn runtime::Caller<'_>,
env: &MetadataContextHostEnvironment,
allocated_ret_ptr: u32,
) -> i32 {
let config_value = env.transform_plugin_config.as_ref();
if let Some(config_value) = config_value {
// Lazy as possible as we can - only deserialize json value if transform plugin
// actually needs it.
let config = serde_json::to_string(config_value).ok();
if let Some(config) = config {
let serialized =
PluginSerializedBytes::try_serialize(&VersionedSerializable::new(config))
.expect("Should be serializable");
allocate_return_values_into_guest(caller, allocated_ret_ptr, &serialized);
return 1;
}
}
0
}
#[cfg_attr(debug_assertions, tracing::instrument(level = "info", skip_all))]
pub fn get_transform_context(
caller: &mut dyn runtime::Caller<'_>,
env: &MetadataContextHostEnvironment,
key: u32,
allocated_ret_ptr: u32,
) -> i32 {
let Some(value) = env
.metadata_contextView on GitHub (pinned to 5176682b65)
Solutions
- Rebuild/pin the plugin against the swc_core version shipped in your @swc/core
- Upgrade @swc/core and the plugin together
- Verify the plugin config is plain JSON (this avoids the silent return-0 path where the plugin sees no config)
- Report upstream if matched versions still crash
Example fix
// before
jsc: { experimental: { plugins: [['my-plugin', cfg]] } } // plugin wasm built on old swc_core
// after
// rebuild my-plugin.wasm against the swc_core in @swc/core, keep config as plain JSON
jsc: { experimental: { plugins: [['my-plugin', { strict: true }]] } } Defensive patterns
Strategy: validation
Validate before calling
// ensure plugin config is plain-JSON serializable and plugin version aligns const cfg = swcCfg.jsc.experimental.plugins[0][1]; JSON.stringify(cfg); // throws early if non-serializable (host would silently pass null otherwise) assertPluginHostAligned(pluginName, coreVersion);
Try / catch
// wrap plugin-enabled compilation in a worker; on native crash, retry once with plugins disabled
const out = await runInWorker('swc-transform', input).catch(() =>
runInWorker('swc-transform', input, { plugins: false })
); Prevention
- Keep plugin config to JSON primitives (no functions, Dates, undefined gaps)
- Version-lock @swc/core and plugins
- Test the plugin config path explicitly in CI after upgrades
When it happens
Trigger: A plugin calls get_transform_config and the CBOR encoding of the config string fails - realistically only when the plugin binary's swc_core schema does not match the host runner, or the runner's encoder is broken.
Common situations: Config passed through @swc/core `jsc.experimental.plugins` with a plugin binary compiled against a different swc_core; partial upgrades; in-house plugins drifting from the app's compiler version.
Related errors
- Should be serializable
- Should be serializable
- Should able to be deserialized into string
- Should able to deserialize
- Should able to read memory from given ptr
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/9c79a578243a1ae6.
Report an issue: GitHub.