{"record":{"id":"c07c65cadeed8e0e","repo":"facebook/flow","slug":"expected-file-got-deserialized-type","errorCode":null,"errorMessage":"Expected File, got ${deserialized.type}","messagePattern":"Expected File, got (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/flow-parser/oxidized-src/FlowParser.js","lineNumber":347,"sourceCode":"      // $FlowExpectedError[prop-missing] SyntaxError loc is a parser extension.\n      syntaxError.loc = {\n        line: flowParseResult_getErrorLine(parseResult),\n        column: flowParseResult_getErrorColumn(parseResult),\n      };\n      throw syntaxError;\n    }\n\n    const deserialized = new FlowParserDeserializer(\n      programBuffer,\n      flowParseResult_getPositionBuffer(parseResult),\n      flowParseResult_getPositionBufferSize(parseResult),\n      flowParseResult_getStringBuffer(parseResult),\n      FlowParserWASM,\n      options,\n    ).deserialize();\n    if (options.babel === true) {\n      if (deserialized.type !== 'File') {\n        throw new Error(`Expected File, got ${deserialized.type}`);\n      }\n      return deserialized;\n    }\n    if (deserialized.type !== 'Program') {\n      throw new Error(`Expected Program, got ${deserialized.type}`);\n    }\n    const ast = deserialized;\n\n    // Wire→ESTree loc/range normalization. The wire format carries\n    // `rangeStart` / `rangeEnd` on the loc object; ESTree consumers expect a\n    // `range: [start, end]` array on the *node* itself, plus a clean\n    // `loc: { source, start, end }`. This walk is the parser-level analog of\n    // upstream HermesToESTreeAdapter.transform()'s mandatory range conversion\n    // (HermesToESTreeAdapter.js:39 — `node.range = [loc.rangeStart, loc.rangeEnd]`).\n    // Lives here (not in src/index.js) so callers that bypass the public\n    // hermes-parser-compatibility wrapper (e.g. the wasm fixture runner that\n    // tests raw Flow ESTree parity with the OCaml parser) still get the\n    // canonical ESTree loc/range shape.","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/facebook/flow/blob/5c865861998a8ccb7dbc82b0c1f511e9ef60c3d9/packages/flow-parser/oxidized-src/FlowParser.js#L329-L365","documentation":"The flow-parser's public parse() API deserializes an AST from the WASM parser and, when the `babel: true` option is set, expects the top-level node to be a Babel-style 'File' node. If the deserialized root has any other type, the parser's internal contract with the WASM output is broken, so it throws rather than returning a malformed AST.","triggerScenarios":"Calling parse() (parse, the public entry) with options.babel === true while the WASM deserializer returns a root node whose type is not 'File' — e.g. a version mismatch between the JS wrapper and the compiled FlowParserWASM, or corrupted/unexpected wire output.","commonSituations":"Mixing flow-parser JS code from one version with WASM artifacts from another build; custom builds of the WASM parser; caching deserialized ASTs across parser upgrades.","solutions":["Ensure the flow-parser package is installed intact and a single version: reinstall node_modules so FlowParser.js and FlowParserWASM come from the same build.","Verify the options you pass to parse(); with babel:true the WASM build must emit File roots — check your wrapper/build doesn't strip or alter the root.","If you only need ESTree output, drop babel:true so the 'Program' branch is used instead."],"exampleFix":"// before\nconst ast = flow.parse(src, { babel: true });\n// after (if ESTree Program is what you consume)\nconst ast = flow.parse(src); // returns Program; no File-type expectation","handlingStrategy":"type-guard","validationCode":"const ast = flow.parse(src, { babel: true });\nif (ast.type !== 'File') {\n  throw new Error('Parser returned non-File root; check flow-parser version integrity');\n}","typeGuard":"const isBabelFile = (n) => n != null && typeof n === 'object' && n.type === 'File';","tryCatchPattern":"try {\n  const ast = flow.parse(src, { babel: true });\n} catch (err) {\n  if (String(err.message).startsWith('Expected File')) {\n    console.error('flow-parser build mismatch; reinstall node_modules');\n  }\n  throw err;\n}","preventionTips":["Keep flow-parser installed as a single intact version (no mixed builds).","Don't cache deserialized ASTs across parser upgrades.","Only pass babel:true when your consumers actually expect Babel File roots."],"tags":["ast","wasm","flow-parser","invariant"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"5c865861998a8ccb7dbc82b0c1f511e9ef60c3d9","analyzedAt":"2026-09-08T04:32:53.179Z","contentChangedAt":"2026-09-08T04:32:53.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}