sinelaw/fresh · error

Semantic errors

Error message

Semantic errors: {}

What it means

After parsing succeeds, `transpile_typescript` runs oxc's semantic analysis; any semantic-level errors reported by SemanticBuilder abort the transpile with this message. The source parsed but failed symbol/scoping analysis needed by the transformer.

Solutions

  1. Fix each reported semantic error in the source (message lists them joined by '; ').
  2. Refactor the offending construct (e.g. move `super` usage into a class method).
  3. If it looks like a false positive, check the oxc version in Cargo.lock and update/downgrade accordingly.
Defensive patterns

Strategy: try-catch

Try / catch

if let Err(e) = transpile_typescript(src, "plugin.ts") {
    if e.to_string().starts_with("Semantic errors") { log::error!("semantic analysis failed: {e}"); }
}

Prevention

When it happens

Trigger: Calling `transpile_typescript` on source that parses but produces semantic errors — rare, typically constructs the analyzer rejects (e.g. `super` outside a class, invalid binding forms).

Common situations: Hand-edited plugin sources with structurally odd code; generated code fed to the transpiler; oxc version differences flagging constructs previously tolerated.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13). Data as JSON: /api/errors/ec5b68f317986bff. Report an issue: GitHub.

Appendix: source

Thrown at crates/fresh-parser-js/src/lib.rs:37

pub fn transpile_typescript(source: &str, filename: &str) -> Result<String> {
    let allocator = Allocator::default();
    let source_type = SourceType::from_path(filename).unwrap_or_default();

    // Parse
    let parser_ret = Parser::new(&allocator, source, source_type).parse();
    if !parser_ret.errors.is_empty() {
        let errors: Vec<String> = parser_ret.errors.iter().map(|e| e.to_string()).collect();
        return Err(anyhow!("TypeScript parse errors: {}", errors.join("; ")));
    }

    let mut program = parser_ret.program;

    // Semantic analysis (required for transformer)
    let semantic_ret = SemanticBuilder::new().build(&program);

    if !semantic_ret.errors.is_empty() {
        let errors: Vec<String> = semantic_ret.errors.iter().map(|e| e.to_string()).collect();
        return Err(anyhow!("Semantic errors: {}", errors.join("; ")));
    }

    // Get scoping info for transformer
    let scoping = semantic_ret.semantic.into_scoping();

    // Transform (strip TypeScript types)
    let transform_options = TransformOptions::default();
    let transformer_ret = Transformer::new(&allocator, Path::new(filename), &transform_options)
        .build_with_scoping(scoping, &mut program);

    if !transformer_ret.errors.is_empty() {
        let errors: Vec<String> = transformer_ret
            .errors
            .iter()
            .map(|e| e.to_string())
            .collect();
        return Err(anyhow!("Transform errors: {}", errors.join("; ")));
    }

View on GitHub (pinned to 67894ca546)