{"record":{"id":"d19ee4758534aa21","repo":"facebook/flow","slug":"tried-to-remove-node-type-from-parent-of-type","errorCode":null,"errorMessage":"Tried to remove ${node.type} from parent of type ${node.parent.type}.\nHowever ${node.type} can only be safely removed from parent of type ArrowFunctionExpression | FunctionDeclaration | FunctionExpression | ArrayExpression | ArrayPattern.","messagePattern":"Tried to remove (.+?) from parent of type (.+?)\\.\nHowever (.+?) can only be safely removed from parent of type ArrowFunctionExpression \\| FunctionDeclaration \\| FunctionExpression \\| ArrayExpression \\| ArrayPattern\\.","errorType":"exception","errorClass":"InvalidRemovalError","httpStatus":null,"severity":"error","filePath":"packages/flow-transform/src/transform/mutations/RemoveNode.js","lineNumber":192,"sourceCode":"\n      case 'Property':\n        assertParent(VALID_PROPERTY_PARENTS);\n        return 'properties';\n\n      // Identifier can be the child of a number of usecases\n      case 'Identifier':\n        switch (node.parent.type) {\n          case 'ArrowFunctionExpression':\n          case 'FunctionDeclaration':\n          case 'FunctionExpression':\n            return 'params';\n\n          case 'ArrayExpression':\n          case 'ArrayPattern':\n            return 'elements';\n\n          default:\n            throw new InvalidRemovalError(\n              getErrorMessage([\n                'ArrowFunctionExpression',\n                'FunctionDeclaration',\n                'FunctionExpression',\n                'ArrayExpression',\n                'ArrayPattern',\n              ]),\n            );\n        }\n\n      // RestElement can be the child of a number of usecases\n      case 'RestElement':\n        switch (node.parent.type) {\n          case 'ArrowFunctionExpression':\n          case 'FunctionDeclaration':\n          case 'FunctionExpression':\n          case 'ComponentDeclaration':\n            return 'params';","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/facebook/flow/blob/d1341dac899a79c027762f6b423d896045287620/packages/flow-transform/src/transform/mutations/RemoveNode.js#L174-L210","documentation":"removeNodeMutation supports removing an Identifier only from array positions it knows how to patch: params of function-like nodes and elements of ArrayExpression/ArrayPattern. Any other parent (a reference in a MemberExpression, a VariableDeclarator id, a Property key) hits the default case and throws InvalidRemovalError listing the allowed parents. Removing a binding identifier from other positions would leave an invalid AST, so it is rejected up front.","triggerScenarios":"removeNodeMutation(identifier) where identifier.parent is a MemberExpression, VariableDeclarator, Property, or CallExpression callee: anything other than ArrowFunctionExpression, FunctionDeclaration, or FunctionExpression (params) or ArrayExpression or ArrayPattern (elements).","commonSituations":"Unused-parameter cleanup codemods that match Identifier nodes too broadly and try to remove references, not just parameters; destructuring-aware cleanup assuming every Identifier sits in a pattern.","solutions":["Narrow the visitor to Identifiers whose parent is a function-like node's params array or an ArrayPattern","For binding removal, remove the enclosing VariableDeclarator or Property instead of the Identifier","Use replaceNodeMutation for positions removal does not support"],"exampleFix":"// before\nif (node.type === 'Identifier') mutations.push(removeNode(node)); // throws for references\n\n// after\nconst P = node.parent;\nif (node.type === 'Identifier' &&\n    (P.type === 'ArrowFunctionExpression' || P.type === 'FunctionDeclaration' || P.type === 'FunctionExpression')) {\n  mutations.push(removeNode(node)); // params only\n}","handlingStrategy":"type-guard","validationCode":"const IDENTIFIER_REMOVE_PARENTS = new Set(['ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression', 'ArrayExpression', 'ArrayPattern']);\nfunction canRemoveIdentifier(node) {\n  return node.type === 'Identifier' && IDENTIFIER_REMOVE_PARENTS.has(node.parent.type);\n}","typeGuard":"const isRemovableIdentifier = (node) =>\n  node.type === 'Identifier' && ['ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression', 'ArrayExpression', 'ArrayPattern'].includes(node.parent && node.parent.type);","tryCatchPattern":null,"preventionTips":["Match Identifiers by parent context (params or elements), never by type alone","To remove a binding, remove the VariableDeclarator or Property that owns it","Read the allowlist out of the error message and encode it as a guard set in your codemod"],"tags":["flow-transform","removal","identifier","parent-type"],"backgroundTag":"unsupported-ast-node-removal","analyzedSha":"d1341dac899a79c027762f6b423d896045287620","analyzedAt":"2026-08-17T00:07:02.212Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}