facebook/flow · error

Invalid Mutation: Tried to mutate an elements array with an…

Error message

Invalid Mutation: Tried to mutate an elements array with an out of bounds index. Index: ${index}, Array Size: ${array.length}

What it means

astArrayMutationHelpers asserts index bounds (0 <= index < array.length) before every element mutation (replaceInArray, removal, insertion helpers). An out-of-range or negative index throws with the offending index and array size, indicating the caller's positional bookkeeping no longer matches the array being mutated.

Solutions

  1. Recompute the index immediately before each mutation (e.g. via array.indexOf(node)) instead of caching it.
  2. Mutate a snapshot plan but resolve indices at apply time against the current array, or rebuild arrays functionally (map/filter) instead of positional splice.
  3. Check bounds before calling: if (i < 0 || i >= arr.length) skip/log.
  4. For removals, prefer identity-based removal (find then filter) over index-based removal.

Example fix

// before
const idx = body.indexOf(target);
forEachOtherNode(() => replaceInArray(body, idx, newNode)); // body changed meanwhile

// after
const idx = body.indexOf(target); // resolve at apply time
if (idx >= 0 && idx < body.length) replaceInArray(body, idx, newNode);
Defensive patterns

Strategy: validation

Validate before calling

// Bounds-check before mutating
function inBounds(array, index) {
  return Number.isInteger(index) && index >= 0 && index < array.length;
}
if (inBounds(body, idx)) replaceInArray(body, idx, newNode);

Type guard

function isValidIndex(array, index) {
  return Number.isInteger(index) && index >= 0 && index < array.length;
}

Prevention

When it happens

Trigger: Calling array-mutation helpers with an index computed before earlier mutations shifted/removed elements (stale index), an index taken from a different array, or an off-by-one (e.g. using array.length as the last index instead of length-1).

Common situations: Codemods that remove several nodes while holding precomputed indices; batched edits applied to an AST that was rebuilt mid-loop; transforms that copy an index across traversal boundaries where sibling counts differ.

Related errors


AI-assisted analysis of facebook/flow@f88ac94bcf (2026-08-20). Data as JSON: /api/errors/964cd7a6f1d62d3b. Report an issue: GitHub.

Appendix: source

Thrown at packages/flow-parser/oxidized-src/transform/astArrayMutationHelpers.js:13

/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow strict
 * @format
 */

function assertArrayBounds<T>(array: ReadonlyArray<T>, index: number): void {
  if (index < 0 || index >= array.length) {
    throw new Error(
      `Invalid Mutation: Tried to mutate an elements array with an out of bounds index. Index: ${index}, Array Size: ${array.length}`,
    );
  }
}

export function arrayIsEqual(
  a1: ReadonlyArray<unknown>,
  a2: ReadonlyArray<unknown>,
): boolean {
  if (a1 === a2) {
    return true;
  }

  if (a1.length !== a2.length) {
    return false;
  }

  for (let i = 0; i < a1.length; i++) {

View on GitHub (pinned to f88ac94bcf)