{"record":{"id":"2bf1128d1da762c0","repo":"swc-project/swc","slug":"key-already-set-previous-value-previous","errorCode":null,"errorMessage":"Key already set. Previous value: {previous:?}","messagePattern":"Key already set\\. Previous value: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/swc_transform_common/src/output.rs","lineNumber":56,"sourceCode":"    )\n    .expect(\"Should able to serialize String\");\n    let (ptr, len) = diag.as_ptr();\n\n    unsafe {\n        __emit_output(ptr as u32, len as u32);\n    }\n}\n\n/// (Experimental) Emits a value to the JS caller.\n///\n/// This is not stable and may be removed in the future.\n#[cfg(not(all(feature = \"plugin-mode\", target_arch = \"wasm32\")))]\npub fn experimental_emit(key: String, value: String) {\n    OUTPUT.with(|output| {\n        let previous = output.borrow_mut().insert(key, value);\n\n        if let Some(previous) = previous {\n            panic!(\"Key already set. Previous value: {previous:?}\");\n        }\n    });\n}\n","sourceCodeStart":38,"sourceCodeEnd":60,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_transform_common/src/output.rs#L38-L60","documentation":"experimental_emit in swc_transform_common::output pushes a key/value pair into the thread-local RefCell<FxHashMap> installed by capture(), forwarding metadata from a transform to the caller. On the native (non-wasm-plugin) path it inserts the key and panics if a value was already stored under it, refusing to silently overwrite a previous emission.","triggerScenarios":"Calling experimental_emit with the same key twice within one capture() scope: a visitor emitting under a fixed key per visited node, a transform emitting per-file metadata while several files are processed inside one captured closure, or the same transform pass running twice.","commonSituations":"Writing SWC plugins/tools that emit debug or metadata with constant keys like \"log\" or \"result\"; emitting inside visit_* methods that fire multiple times; treating this experimental API as an append-only log without uniquing keys.","solutions":["Make keys unique per emission (append a counter, span hash, or file id)","Track already-emitted keys in your own HashSet and skip duplicates before calling experimental_emit","Restructure so each capture() scope emits each key at most once (emit once per file, not per node)","Avoid relying on experimental_emit at all; it is explicitly marked unstable"],"exampleFix":"// before\nexperimental_emit(\"diag\".into(), first.clone());\nexperimental_emit(\"diag\".into(), second.clone()); // panics: Key already set\n\n// after\nexperimental_emit(\"diag-0\".into(), first.clone());\nexperimental_emit(\"diag-1\".into(), second.clone());","handlingStrategy":"validation","validationCode":"use std::collections::HashSet;\n\nlet mut emitted: HashSet<String> = HashSet::new();\n\nfn emit_once(emitted: &mut HashSet<String>, key: &str, value: String) {\n    let unique_key = if emitted.contains(key) {\n        format!(\"{key}-{}\", emitted.len())\n    } else {\n        key.to_string()\n    };\n    emitted.insert(unique_key.clone());\n    swc_transform_common::output::experimental_emit(unique_key, value);\n}","typeGuard":null,"tryCatchPattern":"let res = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    experimental_emit(key.clone(), value.clone())\n}));\nif res.is_err() {\n    // duplicate key: log and continue without aborting the transform\n    log::warn!(\"experimental_emit skipped duplicate key {key}\");\n}","preventionTips":["Never call experimental_emit with a constant key from per-node visitor code","Track emitted keys in your own HashSet and uniquify (counter/span/file id) before emitting","Emit at most once per capture() scope per key","Remember the API is experimental: wrap all uses so it can be swapped out"],"tags":["experimental","thread-local","duplicate-key","panic","swc-transform-common"],"backgroundTag":"duplicate-key-panic","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}