swc-project/swc · error · swc_css_parser::error::Error
Unexpected end of file
Error message
Unexpected end of file
What it means
Input::cur() was called on the token-stream input when the parser has already consumed every token: the position stack ('idx') is empty, so there is no current token to return. The parser surfaces this as an unexpected-EOF error positioned at the end of input. It almost always means the grammar expected more input (a closing brace, paren, or value) but the stylesheet ended.
Source
Thrown at crates/swc_css_parser/src/parser/input.rs:359
res
}
None => return None,
_ => {
unreachable!("Not allowed in the list of component values")
}
}
}
fn cur(&mut self) -> PResult<Cow<'_, TokenAndSpan>> {
match self.input {
InputType::Tokens(input) => {
let idx = match self.idx.last() {
Some(idx) => idx,
_ => {
let bp = input.span.hi;
let span = Span::new(bp, bp);
return Err(Error::new(span, ErrorKind::Eof));
}
};
let token_and_span = match input.tokens.get(*idx) {
Some(token_and_span) => token_and_span,
None => {
let bp = input.span.hi;
let span = Span::new(bp, bp);
return Err(Error::new(span, ErrorKind::Eof));
}
};
Ok(Cow::Borrowed(token_and_span))
}
InputType::ListOfComponentValues(input) => {
let token_and_span = match self.get_component_value(&input.children, 0) {
Some(token_or_block) => match token_or_block {View on GitHub (pinned to 5176682b65)
Solutions
- Balance delimiters: every '{', '(', '[' closed, strings and comments terminated
- If parsing a fragment, wrap or repair it (append the missing closers) before parsing
- For streams, buffer until the stylesheet is complete instead of parsing partial input
- Locate the innermost unclosed construct by counting delimiters from the start of input
Example fix
/* before */
.a { color: red;
/* after */
.a { color: red; } Defensive patterns
Strategy: validation
Validate before calling
// Reject obviously unbalanced/truncated stylesheets before parsing
function isBalanced(css) {
const pairs = { '{': '}', '(': ')', '[': ']' };
const stack = [];
for (const ch of css.replace(/\./g, '').replace(/"[^"]*"|'[^']*'|\/\*[\s\S]*?\*\//g, '')) {
if (pairs[ch]) stack.push(ch);
else if (Object.values(pairs).includes(ch)) { if (pairs[stack.pop()] !== ch) return false; }
}
return stack.length === 0;
} Try / catch
// JS
try { parse(css, opts); } catch (e) { if (/end of file/.test(e.message)) requestMoreInputOrAppendClosers(css); } Prevention
- Never parse partial buffers — buffer streams until EOF
- Auto-append missing closers for CMS/user input before parsing
- Treat Eof-kind errors as 'incomplete input', distinct from syntax errors
When it happens
Trigger: Unclosed '{' (rule block), '(' (media query or declaration value), unclosed string/comment, or a truncated file: '.a { color: red;' or '@media (width { ... }' reaching end of input while the parser still asks for the next token.
Common situations: Incremental/streaming pipelines that feed partial buffers to the parser; files truncated by a failed write or an interrupted network transfer; user-authored CSS in CMS fields where the closing brace was never typed; code that re-parses fragments without balancing delimiters first.
Related errors
- Unexpected end of file
- End of file seen when expecting text or an end tag
- The requested module '{specifier}' does not provide an expor
- attempted to ${action} private field on non-instance
- Expected function or '('
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/12ad420779dbf2b3.
Report an issue: GitHub.