swc-project/swc · error · io::Error
InvalidData
InvalidData
Error message
expected newline
What it means
swc_sourcemap transparently strips the XSSI-protection junk prefix that servers prepend to sourcemap JSON (e.g. `)]}'`). The streaming `StripHeaderReader` scans the leading bytes; after junk bytes it accepts an optional ` ` followed by a required ` `. If a ` ` is seen and the next byte is NOT ` ` (crates/swc_sourcemap/src/decoder.rs:89), the file cannot be a valid junk-prefixed map, so the reader fails with `io::ErrorKind::InvalidData` ('expected newline').
Source
Thrown at crates/swc_sourcemap/src/decoder.rs:89
buf[..read].copy_from_slice(&local_buf[..read]);
self.header_state = HeaderState::PastHeader;
return Ok(read);
}
}
HeaderState::Junk => {
if byte == b'\r' {
HeaderState::AwaitingNewline
} else if byte == b'\n' {
HeaderState::PastHeader
} else {
HeaderState::Junk
}
}
HeaderState::AwaitingNewline => {
if byte == b'\n' {
HeaderState::PastHeader
} else {
Err(io::Error::new(
io::ErrorKind::InvalidData,
"expected newline",
))?
}
}
HeaderState::PastHeader => {
let rem = read - offset;
buf[..rem].copy_from_slice(&local_buf[offset..read]);
return Ok(rem);
}
};
}
}
}
}
pub fn strip_junk_header(slice: &[u8]) -> io::Result<&[u8]> {
if slice.is_empty() || !is_junk_json(slice[0]) {View on GitHub (pinned to 5176682b65)
Solutions
- Rewrite the file so the junk header is exactly `)]}'` followed by one \n and then the JSON
- Remove the XSSI prefix entirely — the decoder also accepts files that start directly with the JSON
- Fix the transfer/editor pipeline that rewrote line endings inside the header (git autocrlf, text-mode FTP)
- If the leading bytes are legitimate content (file truly begins with `)`), re-encode the map so it starts with `{`
Example fix
// before (file bytes)
)]}\r)]}\n{"version":3,...}
// after
)]}'\n{"version":3,...} Defensive patterns
Strategy: try-catch
Validate before calling
// Check the header bytes before handing a reader to the sourcemap decoder
fn header_is_clean(head: &[u8]) -> bool {
let junk: &[u8] = b")]}'";
if !head.starts_with(junk) && !matches!(head.first(), Some(b')' | b']' | b'}' | b'\'')) { return true; }
// after junk bytes, allow at most one \r immediately followed by \n
let mut i = 0;
while i < head.len() && matches!(head[i], b')' | b']' | b'}' | b'\'' ) { i += 1; }
if i < head.len() && head[i] == b'\r' { i += 1; }
i < head.len() && head[i] == b'\n'
} Try / catch
match SourceMap::from_reader(StripHeaderReader::new(file)) {
Ok(sm) => sm,
Err(e) if e.to_string().contains("expected newline") => {
// header is corrupt; strip the prefix manually and retry once from the '{' byte
retry_from_first_brace(file)?
}
Err(e) => return Err(e),
} Prevention
- Serve sourcemaps with the exact `)]}'` + LF prefix, or with no prefix at all
- Disable line-ending conversion for .map files (git attributes, editor settings)
- Add a fixture test asserting the first bytes of every published .map file
When it happens
Trigger: Decoding a sourcemap via a reader (SourceMap/SourceMapIndex from_reader paths) whose first byte is one of `) ] } '` and which contains a carriage return not immediately followed by a line feed inside the header region — e.g. `)]}\rX{"version":3...}` or `)]}'` followed by a second stray CR before the JSON.
Common situations: Sourcemap files mangled by line-ending conversion (git autocrlf, FTP text mode, editor round-trips that turn the single header LF into CR or CRLFCR); custom XSSI guards emitting `)]}'` plus something other than a clean newline; concatenation scripts joining headers incorrectly.
Related errors
- failed to emit error: {e}
- invalid vlq segment size; expected 4 or 5, got {}
- invalid source reference: {src_id}
- invalid name reference: {name_id}
- invalid utf8
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/796f8072d3f1e8bc.
Report an issue: GitHub.