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 | ComponentDeclaration | ArrayPattern | ObjectPattern | CallExpression | OptionalCallExpression | NewExpression.

What it means

The RestElement case of removeNodeMutation allows removal from params (function-likes plus ComponentDeclaration), elements (ArrayPattern), properties (ObjectPattern), and arguments (Call, New, and OptionalCallExpression). Every other parent type falls to the default and throws InvalidRemovalError with the full allowlist in the message. The allowlist exists because each allowed slot is an array the mutation engine can splice safely; other rest positions (e.g. under an AssignmentPattern) would produce unprintable code.

Source

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

          case 'FunctionExpression':
          case 'ComponentDeclaration':
            return 'params';

          case 'ArrayPattern':
            return 'elements';

          case 'ObjectPattern':
            return 'properties';

          // $FlowFixMe[incompatible-type]
          // $FlowFixMe[invalid-compare]
          case 'OptionalCallExpression':
          case 'CallExpression':
          case 'NewExpression':
            return 'arguments';

          default:
            throw new InvalidRemovalError(
              getErrorMessage([
                'ArrowFunctionExpression',
                'FunctionDeclaration',
                'FunctionExpression',
                'ComponentDeclaration',
                'ArrayPattern',
                'ObjectPattern',
                'CallExpression',
                'OptionalCallExpression',
                'NewExpression',
              ]),
            );
        }

      // SpreadElement can be the child of a number of usecases
      case 'SpreadElement':
        switch (node.parent.type) {
          case 'ArrayExpression':

View on GitHub (pinned to d1341dac89)

Solutions

  1. Only request removal when the RestElement's parent type is in the allowlist (check node.parent.type first)
  2. For unsupported positions, replace the enclosing pattern or declarator with a rebuilt node using replaceNodeMutation instead
  3. When the error message prints an unexpected parent type, re-check the traversal: you are likely matching rests in assignments, not params

Example fix

// before
mutations.push(removeNode(node)); // node = RestElement under AssignmentPattern

// after
const OK = ['ArrowFunctionExpression','FunctionDeclaration','FunctionExpression','ComponentDeclaration','ArrayPattern','ObjectPattern','CallExpression','OptionalCallExpression','NewExpression'];
if (OK.includes(node.parent.type)) {
  mutations.push(removeNode(node));
} else {
  mutations.push(replaceWith(node.parent, rebuildWithoutRest(node.parent)));
}
Defensive patterns

Strategy: type-guard

Validate before calling

const REST_REMOVE_PARENTS = new Set(['ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression', 'ComponentDeclaration', 'ArrayPattern', 'ObjectPattern', 'CallExpression', 'OptionalCallExpression', 'NewExpression']);
function canRemoveRestElement(node) {
  return node.type === 'RestElement' && REST_REMOVE_PARENTS.has(node.parent.type);
}

Type guard

const isRemovableRestElement = (node) =>
  node.type === 'RestElement' && ['ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression', 'ComponentDeclaration', 'ArrayPattern', 'ObjectPattern', 'CallExpression', 'OptionalCallExpression', 'NewExpression'].includes(node.parent && node.parent.type);

Prevention

When it happens

Trigger: removeNodeMutation(restElement) where the RestElement's parent is an AssignmentPattern, a VariableDeclarator's pattern, or any node not in the allowlist: for example removing the rest from destructuring assignment where the supported parent chain does not apply.

Common situations: Codemods normalizing function signatures that also walk destructuring sites; refactoring tools that hoist rest params and hit the rest inside assignment destructuring.

Related errors


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