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

  1. Rewrite the file so the junk header is exactly `)]}'` followed by one \n and then the JSON
  2. Remove the XSSI prefix entirely — the decoder also accepts files that start directly with the JSON
  3. Fix the transfer/editor pipeline that rewrote line endings inside the header (git autocrlf, text-mode FTP)
  4. 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

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


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