{"record":{"id":"e465297f7e4f05ed","repo":"swc-project/swc","slug":"failed-to-downgrade-flow-type-only-module-to-scrip","errorCode":null,"errorMessage":"failed to downgrade Flow type-only module to script because module declarations remain after stripping","messagePattern":"failed to downgrade Flow type-only module to script because module declarations remain after stripping","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/swc/src/lib.rs","lineNumber":294,"sourceCode":"            .body\n            .first()\n            .map(Spanned::span)\n            .unwrap_or(module.span);\n        FlowScriptLikeModuleKind::RuntimeModule(span)\n    }\n}\n\nfn downgrade_flow_script_like_module(program: Program) -> Result<Program, Error> {\n    let Program::Module(module) = program else {\n        return Ok(program);\n    };\n\n    if module\n        .body\n        .iter()\n        .any(|module_item| matches!(module_item, ModuleItem::ModuleDecl(..)))\n    {\n        bail!(\n            \"failed to downgrade Flow type-only module to script because module declarations \\\n             remain after stripping\"\n        );\n    }\n\n    let Module {\n        span,\n        body,\n        shebang,\n    } = module;\n\n    let body = body\n        .into_iter()\n        .map(|module_item| match module_item {\n            ModuleItem::Stmt(stmt) => Ok(stmt),\n            ModuleItem::ModuleDecl(..) => bail!(\n                \"failed to downgrade Flow type-only module to script because module declarations \\\n                 remain after stripping\"","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc/src/lib.rs#L276-L312","documentation":"When a file is parsed as Flow in 'script-like module' mode, swc strips Flow types and then downgrades the Program::Module to a Program::Script (crates/swc/src/lib.rs). This bail fires in the pre-conversion scan when module body still contains ModuleItem::ModuleDecl - real runtime module syntax (import/export) survived stripping, so the module cannot be presented as a script.","triggerScenarios":"Configuring `jsc.parser.syntax: flow` for a file that contains actual runtime `import`/`export` statements (not just Flow type-only syntax), so after type stripping module declarations remain and the script downgrade is impossible.","commonSituations":"Pointing the Flow parser at TypeScript or plain ESM files in mixed codebases; sharing one .swcrc between Flow sources and ESM .js files; swc_core versions where Flow stripping of certain module-level type constructs is incomplete.","solutions":["Use the matching parser for the file: typescript (with tsx as needed) or ecmascript, instead of flow","Scope the `flow` syntax config with `test` patterns so it only applies to genuine Flow files","Upgrade swc/swc_core - Flow module-decl stripping behavior has changed across versions","If embedding swc, avoid enabling the flow script-like downgrade path for files with runtime module syntax"],"exampleFix":"// before (.swcrc)\n{ \"jsc\": { \"parser\": { \"syntax\": \"flow\" } } }\n// after (.swcrc)\n{\n  \"test\": \"\\\\.(js|jsx|ts|tsx)$\",\n  \"jsc\": { \"parser\": { \"syntax\": \"typescript\", \"tsx\": true } }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  result = await transformFile(file, flowOptions);\n} catch (e) {\n  if (/downgrade Flow type-only module/.test(String(e?.message ?? e))) {\n    // File has runtime import/export: recompile as TypeScript/ECMAScript\n    result = await transformFile(file, esOptions);\n  } else {\n    throw e;\n  }\n}","preventionTips":["Scope `flow` parser config to genuine Flow files via `test` patterns","Never apply the flow parser to plain ESM/TypeScript sources","Pin swc_core versions you have validated against your Flow corpus"],"tags":["swc","flow","parser","type-stripping","module-to-script"],"backgroundTag":"flow-type-strip-failed","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}