{"record":{"id":"8db5a284b1c33797","repo":"swc-project/swc","slug":"syntax-error","errorCode":null,"errorMessage":"Syntax Error","messagePattern":"Syntax Error","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/swc-ast-explorer/src/parser.rs","lineNumber":18,"sourceCode":"use anyhow::{anyhow, bail, Result};\nuse swc_common::{errors::Handler, SourceFile};\nuse swc_ecma_ast::{EsVersion, Program};\nuse swc_ecma_parser::{parse_file_as_program, Syntax, TsSyntax};\n\n/// Parses a source file as JavaScript, TypeScript, or TSX and returns the SWC\n/// program tree. Recovered parser errors are treated as fatal so the CLI does\n/// not print partial ASTs for invalid input.\npub fn parse_source(file: &SourceFile, handler: &Handler) -> Result<Program> {\n    let syntax = Syntax::Typescript(TsSyntax {\n        tsx: true,\n        ..Default::default()\n    });\n    let mut errors = Vec::new();\n    let program = parse_file_as_program(file, syntax, EsVersion::latest(), None, &mut errors)\n        .map_err(|err| {\n            err.into_diagnostic(handler).emit();\n            anyhow!(\"Syntax Error\")\n        })?;\n\n    let mut has_recovered_error = false;\n    for err in errors {\n        err.into_diagnostic(handler).emit();\n        has_recovered_error = true;\n    }\n\n    if has_recovered_error {\n        bail!(\"Syntax Error\");\n    }\n\n    Ok(program)\n}\n","sourceCodeStart":1,"sourceCodeEnd":33,"githubUrl":"https://github.com/swc-project/swc/blob/d7d74346665e36e692aa07e13d4ee3ee692ee35c/crates/swc-ast-explorer/src/parser.rs#L1-L33","documentation":"Thrown by swc-ast-explorer's parse_source (crates/swc-ast-explorer/src/parser.rs). The file is always parsed as TypeScript with TSX enabled; the error fires both for fatal parse errors and for recovered errors - by design, recovered diagnostics are treated as fatal so the CLI never prints a partial AST for invalid input. The actual diagnostic is emitted to the handler before bailing, so the message itself is intentionally generic.","triggerScenarios":"Running the swc-ast-explorer CLI on a file with any syntax error; feeding TSX/JSX into a context where the TS+TSX grammar still rejects it (e.g. ambiguous '<Type>expr' casts in .ts-mode content, invalid decorators, unfinished template literals); exploring files with proposal syntax the vendored parser version does not support.","commonSituations":"Pointing the explorer at draft or WIP files that do not compile; using an older explorer build against newer language syntax; files that are valid JS but rejected by the stricter TS grammar used unconditionally here.","solutions":["Look at the diagnostic printed above the error - it has the exact line/column - and fix the syntax at that spot","Verify the file parses elsewhere first (tsc --noEmit, or swc CLI with matching syntax) before exploring it","Update swc-ast-explorer so its parser supports the newest syntax used in the file","If the file relies on JS-only syntax the TS grammar misreads, preprocess or rename to an appropriate setup before exploring"],"exampleFix":"// before: ambiguous type-cast syntax breaks the TS grammar\nconst n = <number>value;\n\n// after: use the as-form the TSX-capable grammar accepts\nconst n = value as number;","handlingStrategy":"try-catch","validationCode":"// Skip files that do not even tokenize/parse before exploring\n// (cheap pre-check with the same parser family, e.g. run swc transform once)\nimport { transformSync } from '@swc/core';\nfunction isParseable(filename, code) {\n  try {\n    transformSync(code, { filename, jsc: { parser: { syntax: 'typescript', tsx: true } } });\n    return true;\n  } catch {\n    return false;\n  }\n}","typeGuard":null,"tryCatchPattern":"// CLI context: check exit status and stderr\n// $ swc-ast-explore file.ts 2>diag.txt || handle 'Syntax Error'\n// Library context (Rust):\n// let program = parse_source(&fm, &handler).unwrap_or_else(|e| {\n//     eprintln!(\"explorer cannot parse this file: {e}\");\n//     std::process::exit(1);\n// });","preventionTips":["Run tsc --noEmit or an equivalent parse check before pointing the explorer at a file","Remember the explorer always parses as TS+TSX: avoid syntax legal only in non-TS grammars, and prefer `x as T` casts over `<T>x`","Keep swc-ast-explorer updated so recent proposal syntax is understood"],"tags":["cli","parser","syntax-error","typescript","ast-explorer"],"backgroundTag":null,"analyzedSha":"d7d74346665e36e692aa07e13d4ee3ee692ee35c","analyzedAt":"2026-08-16T12:41:13.160Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}