{"record":{"id":"bf6df1fe354931bd","repo":"facebook/flow","slug":"no-visitor-keys-found-for-node-type-node-type","errorCode":null,"errorMessage":"No visitor keys found for node type \"${node.type}\".","messagePattern":"No visitor keys found for node type \"(.+?)\"\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/flow-parser/oxidized-src/traverse/getVisitorKeys.js","lineNumber":31,"sourceCode":"import type {ESNode} from 'flow-estree';\nimport type {VisitorKeys as VisitorKeysType} from '../generated/ESTreeVisitorKeys';\n\nimport FlowVisitorKeys from '../generated/ESTreeVisitorKeys';\n\nexport function isNode(thing: unknown) /*: implies thing is {readonly [string]: unknown} */ {\n  return (\n    typeof thing === 'object' && thing != null && typeof thing.type === 'string'\n  );\n}\n\nexport type {VisitorKeysType};\nexport function getVisitorKeys<T extends ESNode>(\n  node: T,\n  visitorKeys?: ?VisitorKeysType,\n) /*: ReadonlyArray<keyof T> */ {\n  const keys = (visitorKeys ?? FlowVisitorKeys)[node.type];\n  if (keys == null) {\n    throw new Error(`No visitor keys found for node type \"${node.type}\".`);\n  }\n\n  // $FlowExpectedError[prop-missing]\n  return keys;\n}\n","sourceCodeStart":13,"sourceCodeEnd":37,"githubUrl":"https://github.com/facebook/flow/blob/d1341dac899a79c027762f6b423d896045287620/packages/flow-parser/oxidized-src/traverse/getVisitorKeys.js#L13-L37","documentation":"getVisitorKeys is the single lookup every traversal and transform uses to enumerate a node's child keys; it indexes the visitor-keys map by node.type and throws when there is no entry. The default map is FlowVisitorKeys, which knows exactly the node types flow-parser emits (including Flow type nodes). An unknown type therefore means the AST was not produced by flow-parser, or contains injected or custom nodes.","triggerScenarios":"Feeding an AST from another parser (Babel, Acorn, espree, typescript-eslint) into flow-parser's traverse or SimpleTransform: node types like 'File', 'TSUnionType', 'ChainExpression' have no FlowVisitorKeys entry; injecting custom node types from a visitor; using an outdated flow-parser whose map predates a newer node type.","commonSituations":"Toolchains that mix parsers (lint with espree, transform with flow-parser) and pass ASTs between them; codemods run on TypeScript-in-Flow repos; upgrading one tool but not flow-parser.","solutions":["Only traverse ASTs produced by the same flow-parser version","Pass a custom visitorKeys map via the traversal or transform options that covers your AST dialect's node types","Upgrade flow-parser so FlowVisitorKeys includes the newest node types it emits"],"exampleFix":"// before\ntraverse(babelAst, visitor); // 'File'/'TS*' types unknown -> throws\n\n// after\nconst flowAst = require('flow-parser').parse(source, {});\ntraverse(flowAst, visitor);","handlingStrategy":"validation","validationCode":"import {FlowVisitorKeys} from 'flow-parser'; // or the traverse export your version ships\nfunction assertKnownTypes(ast) {\n  const stack = [ast];\n  while (stack.length) {\n    const n = stack.pop();\n    if (!(n.type in FlowVisitorKeys)) {\n      throw new Error(\"AST contains non-Flow node type '\" + n.type + \"'; reparse with flow-parser\");\n    }\n    for (const k of FlowVisitorKeys[n.type]) {\n      const v = n[k];\n      if (v && typeof v.type === 'string') stack.push(v);\n      else if (Array.isArray(v)) for (const c of v) if (c && typeof c.type === 'string') stack.push(c);\n    }\n  }\n}","typeGuard":"const isKnownNodeType = (type, visitorKeys) => type in (visitorKeys || FlowVisitorKeys);","tryCatchPattern":"try {\n  traverse(ast, visitor);\n} catch (e) {\n  if (e.message.startsWith('No visitor keys found')) {\n    throw new Error('AST dialect mismatch: pass a matching visitorKeys option or reparse with flow-parser');\n  }\n  throw e;\n}","preventionTips":["Only feed ASTs from the same flow-parser version into its traverse and transform","When handling other dialects, pass an explicit visitorKeys map covering every node type you emit","Validate node types up front when accepting ASTs from external tools or serialized caches"],"tags":["ast","traverse","visitor-keys","node-type","flow-parser"],"backgroundTag":"unknown-ast-node-type","analyzedSha":"d1341dac899a79c027762f6b423d896045287620","analyzedAt":"2026-08-17T00:07:02.212Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}