facebook/flow · error · InvalidRemovalError

Tried to remove ${node.type} from parent of type ${node.pare

Error message

Tried to remove ${node.type} from parent of type ${node.parent.type}.
However ${node.type} can only be safely removed from parent of type ArrowFunctionExpression | FunctionDeclaration | FunctionExpression | ArrayExpression | ArrayPattern.

What it means

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.

Source

Thrown at packages/flow-transform/src/transform/mutations/RemoveNode.js:192

      case 'Property':
        assertParent(VALID_PROPERTY_PARENTS);
        return 'properties';

      // Identifier can be the child of a number of usecases
      case 'Identifier':
        switch (node.parent.type) {
          case 'ArrowFunctionExpression':
          case 'FunctionDeclaration':
          case 'FunctionExpression':
            return 'params';

          case 'ArrayExpression':
          case 'ArrayPattern':
            return 'elements';

          default:
            throw new InvalidRemovalError(
              getErrorMessage([
                'ArrowFunctionExpression',
                'FunctionDeclaration',
                'FunctionExpression',
                'ArrayExpression',
                'ArrayPattern',
              ]),
            );
        }

      // RestElement can be the child of a number of usecases
      case 'RestElement':
        switch (node.parent.type) {
          case 'ArrowFunctionExpression':
          case 'FunctionDeclaration':
          case 'FunctionExpression':
          case 'ComponentDeclaration':
            return 'params';

View on GitHub (pinned to d1341dac89)

Solutions

  1. Narrow the visitor to Identifiers whose parent is a function-like node's params array or an ArrayPattern
  2. For binding removal, remove the enclosing VariableDeclarator or Property instead of the Identifier
  3. Use replaceNodeMutation for positions removal does not support

Example fix

// before
if (node.type === 'Identifier') mutations.push(removeNode(node)); // throws for references

// after
const P = node.parent;
if (node.type === 'Identifier' &&
    (P.type === 'ArrowFunctionExpression' || P.type === 'FunctionDeclaration' || P.type === 'FunctionExpression')) {
  mutations.push(removeNode(node)); // params only
}
Defensive patterns

Strategy: type-guard

Validate before calling

const IDENTIFIER_REMOVE_PARENTS = new Set(['ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression', 'ArrayExpression', 'ArrayPattern']);
function canRemoveIdentifier(node) {
  return node.type === 'Identifier' && IDENTIFIER_REMOVE_PARENTS.has(node.parent.type);
}

Type guard

const isRemovableIdentifier = (node) =>
  node.type === 'Identifier' && ['ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression', 'ArrayExpression', 'ArrayPattern'].includes(node.parent && node.parent.type);

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of facebook/flow@d1341dac89 (2026-08-17). Data as JSON: /api/errors/d19ee4758534aa21. Report an issue: GitHub.