swc-project/swc · error · Error

End of file seen when expecting text or an end tag

Error message

End of file seen when expecting text or an end tag

What it means

EOF was reached while the insertion mode was "text" — i.e. the parser was sitting inside an element whose content is consumed as raw text (e.g. `<title>`, `<textarea>`, or any element that switched to generic text parsing) and its end tag never came (parser/mod.rs:4386-4406). This is the `EofInText` parse error; recovery pops the element, restores the original insertion mode, and reprocesses the EOF token so the rest of document close-out runs normally.

Source

Thrown at crates/swc_html_parser/src/parser/mod.rs:4399

                    //
                    // Insert the token's character.
                    Token::Character { .. } => {
                        self.insert_character(token_and_info)?;
                    }
                    // An end-of-file token
                    //
                    // Parse error.
                    //
                    // If the current node is a script element, mark the script element as "already
                    // started".
                    //
                    // Pop the current node off the stack of open elements.
                    //
                    // Switch the insertion mode to the original insertion mode and reprocess the
                    // token.
                    Token::Eof => {
                        self.errors
                            .push(Error::new(token_and_info.span, ErrorKind::EofInText));

                        let popped = self.open_elements_stack.pop();

                        self.update_end_tag_span(popped.as_ref(), token_and_info.span);
                        self.insertion_mode = self.original_insertion_mode.clone();
                        self.process_token(token_and_info, None)?;
                    }
                    // An end tag whose tag name is "script"
                    //
                    // If the active speculative HTML parser is null and the JavaScript execution
                    // context stack is empty, then perform a microtask checkpoint.
                    //
                    // Let script be the current node (which will be a script element).
                    //
                    // Pop the current node off the stack of open elements.
                    //
                    // Switch the insertion mode to the original insertion mode.
                    //

View on GitHub (pinned to 5176682b65)

Solutions

  1. Add the missing end tag (`</title>`, `</textarea>`, etc.) for the element named by the recovery
  2. Check for truncation: verify file size / Content-Length and re-fetch or re-generate the source
  3. Fix template partials so every text-mode element is closed within the same partial
  4. Treat EofInText as a hard data-integrity signal in pipelines (unlike cosmetic tag typos)

Example fix

<!-- before -->
<title>My page

<!-- after -->
<title>My page</title>
Defensive patterns

Strategy: validation

Validate before calling

// Detect an unterminated text-mode element before parsing
fn eof_in_text_element(src: &str) -> bool {
    for el in ["title", "textarea", "style", "xmp", "iframe", "noembed", "noframes", "noscript", "script"] {
        let open = format!("<{el}");
        let close = format!("</{el}");
        if src.contains(&open) {
            let last_open = src.rfind(&open).unwrap_or(0);
            let after = &src[last_open..];
            if !after.contains(&close) { return true; }
        }
    }
    false
}

Type guard

fn is_eof_in_text(e: &Error) -> bool {
    matches!(e.kind, ErrorKind::EofInText)
}

Try / catch

let doc = parser.parse_document()?;
if parser.take_errors().into_iter().any(is_eof_in_text) {
    // input was truncated — everything after this point is lost; do not ship the tree
    return Err(SourceIntegrity::TruncatedInput);
}

Prevention

When it happens

Trigger: `<title>My page` at end of file, `<textarea>user input` with no `</textarea>`, truncated HTML files, or template concatenation that drops a close tag for a text-mode element.

Common situations: Truncated uploads/downloads, network reads cut short, template partials stitched without close tags, and user-generated content saved mid-edit. The trailing text is kept as the element's text content, but everything after the truncation point is gone.

Related errors


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