Unity-Technologies/ml-agents · error · IndexOutOfRangeException

Cannot move cell at row={row} col={col} in Direction={dir}

Error message

Cannot move cell at row={row} col={col} in Direction={dir}

What it means

After confirming the cell is in bounds, FromPositionAndDirection checks whether the swap in the requested direction would push a cell outside the board (e.g. moving Left from column 0). Such a move is impossible, so it throws IndexOutOfRangeException even though the coordinates themselves were valid. Note that Left/Up moves are later normalized to Right/Up, so only edge-adjacent cells in the move direction are rejected.

Source

Thrown at com.unity.ml-agents/Runtime/Integrations/Match3/Move.cs:172

            if (row < 0 || row >= maxBoardSize.Rows)
            {
                throw new IndexOutOfRangeException($"row was {row}, but must be between 0 and {maxBoardSize.Rows - 1}.");
            }

            if (col < 0 || col >= maxBoardSize.Columns)
            {
                throw new IndexOutOfRangeException($"col was {col}, but must be between 0 and {maxBoardSize.Columns - 1}.");
            }

            // Check moves that would go out of bounds e.g. col == 0 and dir == Left
            if (
                row == 0 && dir == Direction.Down ||
                row == maxBoardSize.Rows - 1 && dir == Direction.Up ||
                col == 0 && dir == Direction.Left ||
                col == maxBoardSize.Columns - 1 && dir == Direction.Right
            )
            {
                throw new IndexOutOfRangeException($"Cannot move cell at row={row} col={col} in Direction={dir}");
            }

            // Normalize - only consider Right and Up
            if (dir == Direction.Left)
            {
                dir = Direction.Right;
                col = col - 1;
            }
            else if (dir == Direction.Down)
            {
                dir = Direction.Up;
                row = row - 1;
            }

            int moveIndex;
            if (dir == Direction.Right)
            {
                moveIndex = col + row * (maxBoardSize.Columns - 1);

View on GitHub (pinned to 3ecb446f75)

Solutions

  1. Filter illegal edge moves before calling FromPositionAndDirection (use board.CheckMove, which returns null instead of throwing)
  2. Enumerate Move.GetValidMoves / valid move lists for the cell and pick from those
  3. Clamp direction: rewrite Left→Right on the adjacent cell pair so the swap stays in bounds

Example fix

// before
var move = Move.FromPositionAndDirection(0, 3, Direction.Left, board.MaxBoardSize); // throws
// after
var move = board.CheckMove(0, 3, Direction.Left); // returns null (or swap representation)
if (move != null) { /* apply */ }
Defensive patterns

Strategy: validation

Validate before calling

bool CanShift(int row, int col, Direction dir, BoardSize s) =>
    !(row == 0 && dir == Direction.Down) &&
    !(row == s.Rows - 1 && dir == Direction.Up) &&
    !(col == 0 && dir == Direction.Left) &&
    !(col == s.Columns - 1 && dir == Direction.Right);
// check before calling FromPositionAndDirection

Try / catch

try { var move = Move.FromPositionAndDirection(row, col, dir, board.MaxBoardSize); }
catch (IndexOutOfRangeException e) when (e.Message.Contains("Cannot move cell"))
{ /* skip this action / sample another direction */ }

Prevention

When it happens

Trigger: Requesting Direction.Left from col == 0, Direction.Right from col == Columns-1, Direction.Down from row == 0, or Direction.Up from row == Rows-1 while the move would go out of bounds.

Common situations: Agents randomly sampling directions at board edges; heuristic policies that don't prune edge moves; replayed action logs produced on a differently sized board.

Related errors


AI-assisted analysis of Unity-Technologies/ml-agents@3ecb446f75 (2026-09-02). Data as JSON: /api/errors/fb3539ea27582453. Report an issue: GitHub.