swc-project/swc · error · SyntaxError
Cannot use import.meta outside a module
Error message
Cannot use import.meta outside a module
What it means
The tree-construction step hit a token that cannot legally appear while the parser is in the Start phase (before the root element). Every token type has an explicit arm for the Start phase except the end-tag token, which falls into the `_` catch-all and produces this error; a CDATA section in the prolog is also reported through this same ErrorKind. It is recoverable: the token is simply dropped and parsing continues.
Solutions
- Look at the span in the error to find the exact offset of the offending token, then remove the stray end tag or CDATA section that sits before the root element.
- If you are concatenating fragments, wrap them in a single container element instead of gluing raw chunks together.
- Move any CDATA payload inside the root element where character data is allowed.
- Run the input through a validating XML tool (xmllint or an IDE XML linter) to locate pre-root junk quickly.
Example fix
<!-- before: stray end tag and CDATA before root --> </config> <![CDATA[raw]]> <config/> <!-- after --> <config> <![CDATA[raw]]> </config>
Defensive patterns
Strategy: validation
Validate before calling
use swc_xml_parser::error::ErrorKind;
let mut errors = Vec::new();
let _doc = swc_xml_parser::parse_file_as_document(&fm, config, &mut errors)?;
let stray = errors
.iter()
.filter(|e| matches!(e.kind(), ErrorKind::UnexpectedTokenInStartPhase))
.count();
if stray > 0 {
eprintln!("{stray} stray token(s) before the root element");
} Prevention
- Never concatenate raw XML fragments; build one tree and serialize it once.
- Keep the prolog restricted to the XML declaration, doctype, comments, and processing instructions.
- Lint fixture inputs with a strict XML checker before tests run.
When it happens
Trigger: Input containing a stray end tag before any start tag, e.g. `</root>` at the very beginning, or a stray `</item>` left over from fragment concatenation; or a CDATA section (`<![CDATA[...]]>`) appearing before the root element (that arm also calls append_cdata_to_doc after reporting). Both are reported as ErrorKind::UnexpectedTokenInStartPhase.
Common situations: Concatenating XML fragments (e.g. log chunks or split files) so that a closing tag from a previous chunk lands before the new root element; template engines emitting `]]>`-style raw blocks in the prolog; hand-edited XML where a closing tag was kept after deleting its opening tag.
Related errors
- Assignment to constant variable.
- attempted to private field on non-instance
- attempted to get private field on non-instance
- attempted to reassign private method
- attempted to use private field on non-instance
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/a2f3bedd3bf7ef06.
Report an issue: GitHub.
Appendix: source
Thrown at bindings/binding_nodejs_support_wasm/src/nodejs.rs:1144
fn import_binding_access(binding: &ImportBinding) -> String {
format!(
"{}{}",
binding.namespace,
export_property_access(&binding.export_name)
)
}
fn export_property_access(export_name: &str) -> String {
if is_identifier_name(export_name) {
format!(".{export_name}")
} else {
format!("[{}]", json_string(export_name))
}
}
fn import_meta_error_expression() -> String {
"(() => { throw new SyntaxError(\"Cannot use import.meta outside a module\"); })()".to_string()
}
fn import_assignment_error_expression() -> String {
"(() => { throw new TypeError(\"Assignment to constant variable.\"); })()".to_string()
}
fn is_identifier_name(value: &str) -> bool {
let mut chars = value.chars();
let Some(first) = chars.next() else {
return false;
};
if !(first == '_' || first == '$' || first.is_ascii_alphabetic()) {
return false;
}
chars.all(|ch| ch == '_' || ch == '$' || ch.is_ascii_alphanumeric())
}View on GitHub (pinned to 5176682b65)