{"record":{"id":"9c79a578243a1ae6","repo":"swc-project/swc","slug":"should-be-serializable-9c79a5","errorCode":null,"errorMessage":"Should be serializable","messagePattern":"Should be serializable","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/swc_plugin_runner/src/imported_fn/metadata_context.rs","lineNumber":63,"sourceCode":"    let mut buf = env.mutable_context_key_buffer.lock();\n    copy_bytes_into_host(caller, bytes_ptr, bytes_ptr_len, &mut buf);\n}\n\n#[cfg_attr(debug_assertions, tracing::instrument(level = \"info\", skip_all))]\npub fn get_transform_plugin_config(\n    caller: &mut dyn runtime::Caller<'_>,\n    env: &MetadataContextHostEnvironment,\n    allocated_ret_ptr: u32,\n) -> i32 {\n    let config_value = env.transform_plugin_config.as_ref();\n    if let Some(config_value) = config_value {\n        // Lazy as possible as we can - only deserialize json value if transform plugin\n        // actually needs it.\n        let config = serde_json::to_string(config_value).ok();\n        if let Some(config) = config {\n            let serialized =\n                PluginSerializedBytes::try_serialize(&VersionedSerializable::new(config))\n                    .expect(\"Should be serializable\");\n\n            allocate_return_values_into_guest(caller, allocated_ret_ptr, &serialized);\n\n            return 1;\n        }\n    }\n    0\n}\n\n#[cfg_attr(debug_assertions, tracing::instrument(level = \"info\", skip_all))]\npub fn get_transform_context(\n    caller: &mut dyn runtime::Caller<'_>,\n    env: &MetadataContextHostEnvironment,\n    key: u32,\n    allocated_ret_ptr: u32,\n) -> i32 {\n    let Some(value) = env\n        .metadata_context","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_plugin_runner/src/imported_fn/metadata_context.rs#L45-L81","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\n jsc: { experimental: { plugins: [['my-plugin', cfg]] } } // plugin wasm built on old swc_core\n\n// after\n// rebuild my-plugin.wasm against the swc_core in @swc/core, keep config as plain JSON\n jsc: { experimental: { plugins: [['my-plugin', { strict: true }]] } }","handlingStrategy":"validation","validationCode":"// ensure plugin config is plain-JSON serializable and plugin version aligns\nconst cfg = swcCfg.jsc.experimental.plugins[0][1];\nJSON.stringify(cfg); // throws early if non-serializable (host would silently pass null otherwise)\nassertPluginHostAligned(pluginName, coreVersion);","typeGuard":null,"tryCatchPattern":"// wrap plugin-enabled compilation in a worker; on native crash, retry once with plugins disabled\nconst out = await runInWorker('swc-transform', input).catch(() =>\n  runInWorker('swc-transform', input, { plugins: false })\n);","preventionTips":["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"],"tags":["plugin","wasm","cbor","serialization","config","version-mismatch","panic"],"backgroundTag":"plugin-host-version-mismatch","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}