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
- Filter illegal edge moves before calling FromPositionAndDirection (use board.CheckMove, which returns null instead of throwing)
- Enumerate Move.GetValidMoves / valid move lists for the cell and pick from those
- 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
- Use board.CheckMove or Move.GetValidMoves instead of constructing moves from raw coordinates
- Prune edge-direction combinations when sampling actions at board borders
- Remember Left/Up are normalized to Right/Up — encode moves on the in-bounds side of the pair
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
- row was {row}, but must be between 0 and {maxBoardSize.Rows
- col was {col}, but must be between 0 and {maxBoardSize.Colum
- height value {h} must be in range [0, {m_TensorShape.Height(
- width value {w} must be in range [0, {m_TensorShape.Width()
- channel value {ch} must be in range [0, {m_TensorShape.Chann
AI-assisted analysis of Unity-Technologies/ml-agents@3ecb446f75 (2026-09-02).
Data as JSON: /api/errors/fb3539ea27582453.
Report an issue: GitHub.