swc-project/swc · warning · swc_html_parser::error::Error
Non-space characters found without seeing a doctype first, e
Error message
Non-space characters found without seeing a doctype first, expected "<!DOCTYPE html>"
What it means
Initial insertion mode, 'anything else' branch (crates/swc_html_parser/src/parser/mod.rs:1426): the first token is a character token that is not ASCII whitespace, no doctype preceded it, and iframe_srcdoc is false. Parse error; quirks mode is set and the character is reprocessed downstream. Leading whitespace is ignored by the initial mode and does NOT trigger this.
Source
Thrown at crates/swc_html_parser/src/parser/mod.rs:1426
// In any case, switch the insertion mode to "before html", then reprocess the
// token.
_ => {
if !self.config.iframe_srcdoc {
match &token {
Token::StartTag { .. } => {
self.errors.push(Error::new(
token_and_info.span,
ErrorKind::StartTagWithoutDoctype,
));
}
Token::EndTag { .. } => {
self.errors.push(Error::new(
token_and_info.span,
ErrorKind::EndTagSeenWithoutDoctype,
));
}
Token::Character { .. } => {
self.errors.push(Error::new(
token_and_info.span,
ErrorKind::NonSpaceCharacterWithoutDoctype,
));
}
Token::Eof => {
self.errors.push(Error::new(
token_and_info.span,
ErrorKind::EofWithoutDoctype,
));
}
_ => {
unreachable!();
}
}
self.set_document_mode(DocumentMode::Quirks);
}
View on GitHub (pinned to 5176682b65)
Solutions
- Prepend `<!DOCTYPE html>` and proper markup if the input is meant to be HTML
- Check the content type before parsing — plain text should not go through the HTML parser
- Set ParserConfig { iframe_srcdoc: true, .. } for fragment-like input
Example fix
// before let fm = cm.new_source_file(file.into(), "hello world, no markup".into()); let doc = parse_file_as_document(&fm, config, &mut errors)?; // NonSpaceCharacterWithoutDoctype // after let fm = cm.new_source_file(file.into(), "<!DOCTYPE html>hello world".into()); let doc = parse_file_as_document(&fm, config, &mut errors)?;
Defensive patterns
Strategy: validation
Validate before calling
fn starts_with_nonspace_text(html: &str) -> bool {
let mut rest = html.trim_start();
while let Some(t) = rest.strip_prefix("<!--") {
match t.find("-->") {
Some(i) => rest = t[i + 3..].trim_start(),
None => return false,
}
}
let lower = rest.to_ascii_lowercase();
!lower.is_empty() && !lower.starts_with("<!doctype") && !rest.starts_with('<')
} Try / catch
use swc_html_parser::error::ErrorKind;
let mut errors = Vec::new();
let doc = swc_html_parser::parse_file_as_document(&fm, config, &mut errors)?;
for err in &errors {
if matches!(err.kind(), ErrorKind::NonSpaceCharacterWithoutDoctype) {
log::warn!("bare leading text; input may not be HTML at all");
}
} Prevention
- Content-sniff before parsing: text/plain content should skip the HTML parser
- Wrap prose fragments in minimal `<div>...</div>` plus doctype when a Document is required
- Set iframe_srcdoc = true for srcdoc parsing
When it happens
Trigger: Input whose first non-whitespace, non-comment content is text, e.g. `hello world` or `404: page not found` parsed as HTML with no doctype.
Common situations: Plain-text files fed to the HTML parser by content-sniffing code, error pages, template fragments starting with prose, log output wrapped in HTML parsing.
Related errors
- Non conforming doctype
- Start tag seen without seeing a doctype first, expected "<!D
- End tag seen without seeing a doctype first, expected "<!DOC
- End of file seen without seeing a doctype first, expected "<
- Stray doctype
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/a6fa87e37ea15f9f.
Report an issue: GitHub.