swc-project/swc · warning · Error
Non-space character after "frameset"
Error message
Non-space character after "frameset"
What it means
A non-whitespace character token was dispatched in the 'after frameset' insertion mode. The spec says: parse error, ignore the token — text after the frameset is closed is dropped from the tree entirely. NonSpaceCharacterAfterFrameset records the discarded text with its span.
Source
Thrown at crates/swc_html_parser/src/parser/mod.rs:6521
// Process the token using the rules for the "in head" insertion mode.
Token::StartTag { tag_name, .. } if tag_name == "noframes" => {
self.process_token_using_rules(token_and_info, InsertionMode::InHead)?;
}
// An end-of-file token
//
// Stop parsing.
Token::Eof => {
self.stopped = true;
}
// Anything else
//
// Parse error. Ignore the token.
_ => match token {
// Doctype handled above
// Comment handled above
// EOF handled above
Token::Character { .. } => {
self.errors.push(Error::new(
token_and_info.span,
ErrorKind::NonSpaceCharacterAfterFrameset,
));
}
Token::StartTag { tag_name, .. } => {
self.errors.push(Error::new(
token_and_info.span,
ErrorKind::StrayStartTag(tag_name.clone()),
));
}
Token::EndTag { tag_name, .. } => {
self.errors.push(Error::new(
token_and_info.span,
ErrorKind::StrayEndTag(tag_name.clone()),
));
}
_ => {
unreachable!()View on GitHub (pinned to 5176682b65)
Solutions
- Remove the trailing text, or relocate it into a <noframes> block or the frame's own document.
- Fix include order so appended content lands inside a frame target, not after </frameset>.
- If third-party, filter ErrorKind::NonSpaceCharacterAfterFrameset; note the text is dropped, not relocated.
Example fix
<!-- before --> <frameset cols="*"><frame src="a.html"></frameset> Copyright 2026 Acme </html> <!-- after --> <frameset cols="*"> <frame src="a.html"> <noframes>Copyright 2026 Acme</noframes> </frameset> </html>
Defensive patterns
Strategy: validation
Validate before calling
// Non-whitespace text between </frameset> and </html> (or EOF).
fn has_text_between(src: &str, start_close: &str, end_close: &str) -> bool {
let lower = src.to_ascii_lowercase();
if let Some(s) = lower.find(start_close) {
let rest = &lower[s + start_close.len()..];
let end = rest.find(end_close).unwrap_or(rest.len());
return rest[..end].chars().any(|c| !c.is_ascii_whitespace() && c != '<');
}
false
}
// has_text_between(&html, "</frameset>", "</html>") Type guard
use swc_html_parser::error::{Error, ErrorKind};
fn is_non_space_after_frameset(err: &Error) -> bool {
matches!(err.kind(), ErrorKind::NonSpaceCharacterAfterFrameset)
} Try / catch
let mut errors = Vec::new();
let doc = parse_file_as_document(&fm, config, &mut errors)?;
if errors.iter().any(is_non_space_after_frameset) {
log::warn!("text after </frameset> was dropped");
} Prevention
- Nothing visible may follow </frameset>; put fallback content in <noframes>.
- Check include order in SSI/CGI pipelines that append to frameset pages.
- This text is dropped, not relocated — verify the output tree.
When it happens
Trigger: Visible text after </frameset>, e.g. `<html><frameset cols="*"><frame src="a.html"></frameset>footer text</html>`. The 'anything else' arm of AfterFrameset mode pushes the error for the Character case.
Common situations: Footers or copyright lines appended to legacy frameset pages; SSI includes adding text at the end of the document; automated appenders writing banners after the frameset.
Related errors
- Non-space character in "frameset"
- Non-space character after body
- NonSpaceCharacterInTrailer
- Non-space characters found without seeing a doctype first, e
- End of file seen and there were open elements
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/15c2f87f487f3fec.
Report an issue: GitHub.