{"record":{"id":"06151d03669c2d2e","repo":"swc-project/swc","slug":"unexpected-end-of-file-06151d","errorCode":null,"errorMessage":"Unexpected end of file","messagePattern":"Unexpected end of file","errorType":"validation","errorClass":"swc_css_parser::error::Error","httpStatus":null,"severity":"error","filePath":"crates/swc_css_parser/src/parser/macros.rs","lineNumber":60,"sourceCode":"        tok!($t)\n    };\n}\n\nmacro_rules! cur {\n    ($parser:expr) => {\n        match $parser.input.cur() {\n            Some(v) => v,\n            None => {\n                let last_pos = $parser.input.last_pos();\n                let span = swc_common::Span::new(last_pos, last_pos);\n\n                for error in $parser.input.take_errors() {\n                    let (span, kind) = *error.into_inner();\n\n                    $parser.errors.push(Error::new(span, kind));\n                }\n\n                return Err(crate::error::Error::new(span, crate::error::ErrorKind::Eof));\n            }\n        }\n    };\n}\n\nmacro_rules! bump {\n    ($parser:expr) => {\n        $parser.input.bump().unwrap().token\n    };\n}\n\nmacro_rules! is_case_insensitive_ident {\n    ($parser:expr, $tt:tt) => {{\n        match $parser.input.cur() {\n            Some(swc_css_ast::Token::Ident { value, .. })\n                if (&**value).eq_ignore_ascii_case($tt) =>\n            {\n                true","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_css_parser/src/parser/macros.rs#L42-L78","documentation":"This is the cur!() parser macro: it calls Input::cur(), and when that fails (no current token left) it converts the failure into ErrorKind::Eof at the last position, first draining any lexer errors accumulated on the input into the parser error list. So the visible 'Unexpected end of file' may ride along with earlier lexer diagnostics that were deferred until now.","triggerScenarios":"Any parse rule that calls cur!() after the token stream is exhausted — typically inside a loop that expects more tokens, e.g. parsing declaration values or selector lists of an unclosed block: '.a { color: red;' then the value loop calls cur!() past the end.","commonSituations":"Unclosed rules at EOF (most common), and secondarily stylesheets whose early lexing errors were buffered: the EOF message is what surfaces, but the root cause may be an earlier invalid token — inspect the full error list, not just the last one.","solutions":["Close unclosed blocks/parens/strings and re-parse","Inspect ALL collected errors (the macro flushes deferred lexer errors before returning EOF) — fix the earliest one first","For tooling, treat Eof kind with empty-position span as 'incomplete input' signal and request the rest of the stream"],"exampleFix":"/* before */\n.a { color: red;\n/* after */\n.a { color: red; }","handlingStrategy":"try-catch","validationCode":"// Pre-flight: balanced delimiters and terminated strings/comments catch most causes\nif (!isBalanced(css) || /\\/\\*(?!.*\\*\\/)/s.test(css)) throw new Error('incomplete stylesheet');","typeGuard":null,"tryCatchPattern":"// Rust: Eof here flushes deferred lexer errors — drain ALL errors, fix the first\nmatch parse_string(css) {\n  Err(e) => { for err in parser.errors.iter() { diagnostics.push(err.clone()); } Err(first_diagnostic()) }\n  ok => ok,\n}","preventionTips":["Always inspect the full error list; the EOF message may mask an earlier lexer error","Fail fast on truncated files (check byte length / transfer completion) before parsing"],"tags":["css","parser","eof","lexer"],"backgroundTag":"unexpected-eof-parse-error","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}