swc-project/swc · error · swc_css_parser::error::Error
Expected url or function
Error message
Expected url or function
What it means
Thrown by Parse<DocumentPreludeMatchingFunction> while parsing the prelude of @document. Every item in the comma-separated URL-matching list must be either a url() token or another function — the legacy Firefox matching functions url-prefix(), domain(), regexp(), or src(). If the current token is neither, ErrorKind::Expected("url or function") is returned for that position. @document is legacy Firefox-only syntax, so this prelude is stricter than most at-rules.
Source
Thrown at crates/swc_css_parser/src/parser/at_rules/mod.rs:1311
match cur!(self) {
tok!("url") => Ok(DocumentPreludeMatchingFunction::Url(self.parse()?)),
Token::Function {
value: function_name,
..
} => {
if matches_eq_ignore_ascii_case!(function_name, "url", "src") {
Ok(DocumentPreludeMatchingFunction::Url(self.parse()?))
} else {
// TODO improve me
let function = self.parse()?;
Ok(DocumentPreludeMatchingFunction::Function(function))
}
}
_ => {
let span = self.input.cur_span();
Err(Error::new(span, ErrorKind::Expected("url or function")))
}
}
}
}
impl<I> Parse<MediaQueryList> for Parser<I>
where
I: ParserInput,
{
fn parse(&mut self) -> PResult<MediaQueryList> {
let query: MediaQuery = self.parse()?;
let mut queries = vec![query];
// TODO error recovery
// To parse a <media-query-list> production, parse a comma-separated list of
// component values, then parse each entry in the returned list as a
// <media-query>. Its value is the list of <media-query>s so produced.
loop {View on GitHub (pinned to 5176682b65)
Solutions
- Wrap plain URLs: @document url(https://example.com) { }
- Use the matching functions for the other forms: url-prefix("https://"), domain("example.com"), regexp("https:.*")
- Drop the @document rule entirely — it is not supported by modern engines and keeps the parse from succeeding
- If you gate imports by URL, move the decision into the bundler instead of CSS
Example fix
/* before */
@document "https://example.com/" {
h1 { color: red; }
}
/* after */
@document url-prefix("https://example.com/") {
h1 { color: red; }
} Defensive patterns
Strategy: try-catch
Validate before calling
fn document_prelude_ok(css: &str) -> bool {
let prelude = css.split_once('{').map_or(css, |(p, _)| p);
for item in prelude.split(',') {
let t = item.trim();
if t.is_empty() {
return false;
}
let head = t.split('(').next().unwrap_or("").trim();
let is_fn = t.contains('(') && t.ends_with(')');
let is_url_tok = head.eq_ignore_ascii_case("url") && !t.starts_with('"');
if !(is_fn || is_url_tok) {
return false;
}
}
true
} Type guard
fn is_document_prelude_error(e: &swc_css_parser::error::Error) -> bool {
matches!(e.kind(), swc_css_parser::error::ErrorKind::Expected(m) if *m == "url or function")
} Try / catch
match parse_file::<Stylesheet>(&fm, None, config, &mut errors) {
Ok(sheet) => handle(sheet),
Err(err) if is_document_prelude_error(&err) => {
// legacy Firefox-only rule: safest recovery is to drop @document blocks at generation time
log_and_strip_at_rule(css, *err.into_inner().0, "@document");
}
Err(err) => return Err(err.into()),
} Prevention
- Do not emit @document for cross-browser builds; gate imports in the bundler instead
- Wrap every URL in url() / url-prefix() / domain() / regexp()
- Strip legacy Firefox UA stylesheets before modern tooling
- Reject any @document comma item that is a bare string or ident
When it happens
Trigger: '@document "https://example.com" { }' (a string instead of url(...)), '@document example.com { }' (bare ident), '@document #frag { }', or a comma item that is a number/dimension/string rather than a function token.
Common situations: Porting old Firefox user-stylesheets or UA CSS forward, generated CSS where a URL was interpolated without the url() wrapper, and code that assumes other engines parse @document (they do not, so the whole sheet fails in swc-based tooling).
Related errors
- Expected function or '('
- Expected ident (exclude the keywords 'only', 'not', 'and', '
- Expected identifier value
- Expected '>' or '<' operators
- Expected number, ident, dimension or function token
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/6bab1cdaac6f5ccb.
Report an issue: GitHub.