{"record":{"id":"3c0b2987401b22ac","repo":"swc-project/swc","slug":"failed-to-convert-rawvalue-to-data","errorCode":null,"errorMessage":"Failed to convert RawValue to Data","messagePattern":"Failed to convert RawValue to Data","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/swc_sourcemap/src/lazy/mod.rs","lineNumber":116,"sourceCode":"    T: Deserialize<'de>,\n{\n    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>\n    where\n        D: Deserializer<'de>,\n    {\n        let raw: &'de RawValue = Deserialize::deserialize(deserializer)?;\n        Ok(MaybeRawValue::RawValue(raw))\n    }\n}\n\nimpl<'a, T> MaybeRawValue<'a, T>\nwhere\n    T: Deserialize<'a>,\n{\n    pub fn into_data(self) -> T {\n        match self {\n            MaybeRawValue::RawValue(s) => {\n                serde_json::from_str(s.get()).expect(\"Failed to convert RawValue to Data\")\n            }\n            MaybeRawValue::Data(data) => data,\n        }\n    }\n\n    fn assert_raw_value(self) -> &'a RawValue {\n        match self {\n            MaybeRawValue::RawValue(s) => s,\n            MaybeRawValue::Data(_) => unreachable!(\"Expected RawValue, got Data\"),\n        }\n    }\n}\n\nimpl<T> Default for MaybeRawValue<'_, T>\nwhere\n    T: Default,\n{\n    fn default() -> Self {","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_sourcemap/src/lazy/mod.rs#L98-L134","documentation":"swc_sourcemap's lazy decoder stores JSON fields (sources, sourcesContent, names, ignoreList, file) as raw &RawValue and converts them on first access. into_data() runs serde_json::from_str on that raw fragment into the concrete type and expects success; the panic means the field's JSON shape does not match the sourcemap schema - e.g. names containing numbers, sources being a string instead of an array, ignoreList containing non-integers.","triggerScenarios":"Decoding a third-party or hand-edited .map with SourceMap::from_reader/from_slice (lazy path) and then touching a lazily stored field: building tokens (sources/names), reading file, or querying ignoreList.","commonSituations":"Consuming sourcemaps emitted by other tools (esbuild, terser, rollup, Closure) with non-standard field types; truncated or manually mangled .map files; schema drift between producer and swc_sourcemap's expectations.","solutions":["Pre-validate the .map JSON with serde_json::Value and check field shapes (sources/names: array of strings; ignoreList: array of numbers) before handing it to swc_sourcemap.","Fix the producer of the malformed map or normalize the JSON before decoding.","Force conversion eagerly right after decode inside catch_unwind so the failure happens at a controlled point with your own error message.","Re-serialize the map through a lenient parser (serde_json::Value) into canonical shape, then decode with swc_sourcemap."],"exampleFix":"// before: malformed field panics later, far from the decode site\nlet sm = SourceMap::from_reader(file)?;\nlet src = sm.get_source(0); // may hit expect(\"Failed to convert RawValue to Data\")\n\n// after: validate shapes before decoding\nlet v: serde_json::Value = serde_json::from_reader(file)?;\nlet ok = v[\"sources\"].as_array().map(|a| a.iter().all(|s| s.is_string())).unwrap_or(false)\n    && v[\"names\"].as_array().map(|a| a.iter().all(|s| s.is_string())).unwrap_or(true);\nif !ok { anyhow::bail!(\"invalid sourcemap: sources/names must be string arrays\"); }","handlingStrategy":"validation","validationCode":"// Validate the sourcemap JSON shape before the lazy decoder stores raw\n// fragments that later convert with expect().\npub fn sourcemap_shape_ok(v: &serde_json::Value) -> bool {\n    let arr_of = |node: &serde_json::Value, pred: fn(&serde_json::Value) -> bool| {\n        node.as_array().map(|a| a.iter().all(pred)).unwrap_or(false)\n    };\n    v.get(\"sources\").map(|s| arr_of(s, |x| x.is_string() || x.is_null())).unwrap_or(false)\n        && v.get(\"names\").map(|n| arr_of(n, |x| x.is_string())).unwrap_or(true)\n        && v.get(\"ignoreList\")\n            .map(|n| arr_of(n, |x| x.is_u64()))\n            .unwrap_or(true)\n}","typeGuard":"fn is_conforming_sourcemap(v: &serde_json::Value) -> bool {\n    v.is_object()\n        && v.get(\"version\").map(|x| x.is_u32() || x.is_null()).unwrap_or(true)\n        && v.get(\"mappings\").map(|x| x.is_string()).unwrap_or(true)\n        && v.get(\"sources\").map(|x| x.is_array()).unwrap_or(true)\n}","tryCatchPattern":"// Force lazy conversion at a controlled point; convert the panic to an error.\nlet sm = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    let sm = sourcemap::SourceMap::from_reader(reader)?;\n    // touch every lazily stored field to materialize it now\n    let _ = sm.sources().count();\n    let _ = sm.names().count();\n    Ok::<_, anyhow::Error>(sm)\n}))\n.map_err(|_| anyhow::anyhow!(\"sourcemap fields do not match the expected schema\"))?;","preventionTips":["Validate third-party .map files (shape check or JSON schema) before decoding.","Prefer producers that emit spec-conformant maps; pin their versions.","Materialize lazy fields immediately after decode inside catch_unwind in ingestion code.","Add fixtures for every external map format you ingest so schema drift fails CI, not production."],"tags":["sourcemap","serde","json","deserialization","panic"],"backgroundTag":"sourcemap-parse-failed","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"}