swc-project/swc · critical
Failed to convert RawValue to Data
Error message
Failed to convert RawValue to Data
What it means
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.
Source
Thrown at crates/swc_sourcemap/src/lazy/mod.rs:116
T: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let raw: &'de RawValue = Deserialize::deserialize(deserializer)?;
Ok(MaybeRawValue::RawValue(raw))
}
}
impl<'a, T> MaybeRawValue<'a, T>
where
T: Deserialize<'a>,
{
pub fn into_data(self) -> T {
match self {
MaybeRawValue::RawValue(s) => {
serde_json::from_str(s.get()).expect("Failed to convert RawValue to Data")
}
MaybeRawValue::Data(data) => data,
}
}
fn assert_raw_value(self) -> &'a RawValue {
match self {
MaybeRawValue::RawValue(s) => s,
MaybeRawValue::Data(_) => unreachable!("Expected RawValue, got Data"),
}
}
}
impl<T> Default for MaybeRawValue<'_, T>
where
T: Default,
{
fn default() -> Self {View on GitHub (pinned to 5176682b65)
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.
Example fix
// before: malformed field panics later, far from the decode site
let sm = SourceMap::from_reader(file)?;
let src = sm.get_source(0); // may hit expect("Failed to convert RawValue to Data")
// after: validate shapes before decoding
let v: serde_json::Value = serde_json::from_reader(file)?;
let ok = v["sources"].as_array().map(|a| a.iter().all(|s| s.is_string())).unwrap_or(false)
&& v["names"].as_array().map(|a| a.iter().all(|s| s.is_string())).unwrap_or(true);
if !ok { anyhow::bail!("invalid sourcemap: sources/names must be string arrays"); } Defensive patterns
Strategy: validation
Validate before calling
// Validate the sourcemap JSON shape before the lazy decoder stores raw
// fragments that later convert with expect().
pub fn sourcemap_shape_ok(v: &serde_json::Value) -> bool {
let arr_of = |node: &serde_json::Value, pred: fn(&serde_json::Value) -> bool| {
node.as_array().map(|a| a.iter().all(pred)).unwrap_or(false)
};
v.get("sources").map(|s| arr_of(s, |x| x.is_string() || x.is_null())).unwrap_or(false)
&& v.get("names").map(|n| arr_of(n, |x| x.is_string())).unwrap_or(true)
&& v.get("ignoreList")
.map(|n| arr_of(n, |x| x.is_u64()))
.unwrap_or(true)
} Type guard
fn is_conforming_sourcemap(v: &serde_json::Value) -> bool {
v.is_object()
&& v.get("version").map(|x| x.is_u32() || x.is_null()).unwrap_or(true)
&& v.get("mappings").map(|x| x.is_string()).unwrap_or(true)
&& v.get("sources").map(|x| x.is_array()).unwrap_or(true)
} Try / catch
// Force lazy conversion at a controlled point; convert the panic to an error.
let sm = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
let sm = sourcemap::SourceMap::from_reader(reader)?;
// touch every lazily stored field to materialize it now
let _ = sm.sources().count();
let _ = sm.names().count();
Ok::<_, anyhow::Error>(sm)
}))
.map_err(|_| anyhow::anyhow!("sourcemap fields do not match the expected schema"))?; Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Invalid attempt to iterate non-iterable instance. In order t
- jsonify: Expr {:?} cannot be converted to json
- GenericFailure
- Should able to be deserialized into string
- Should able to deserialize
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/3c0b2987401b22ac.
Report an issue: GitHub.