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

  1. 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.
  2. If you are concatenating fragments, wrap them in a single container element instead of gluing raw chunks together.
  3. Move any CDATA payload inside the root element where character data is allowed.
  4. 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

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


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)