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

  1. 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.
  2. Fix the producer of the malformed map or normalize the JSON before decoding.
  3. Force conversion eagerly right after decode inside catch_unwind so the failure happens at a controlled point with your own error message.
  4. 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

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


AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17). Data as JSON: /api/errors/3c0b2987401b22ac. Report an issue: GitHub.