```ts
/**
 * Determines if the cell at the specified row and column in the grid holds the given value.
 * @param grid - The 2D array representing the grid.
 * @param row - The row index of the cell to check.
 * @param column - The column index of the cell to check.
 * @param value - The value to match against the cell's content.
 * @returns true if the cell holds the value, false otherwise.
 */
export function matchAt(grid: number[][], row: number, column: number, value: number): boolean {
    if (row < 0 || row >= grid.length || column < 0 || column >= grid[row].length) {
        throw new Error("Invalid row or column index");
    }
    return grid[row][column] === value;
}

/**
 * Finds the first occurrence of a cell holding the given value in the grid, reading row by row.
 * @param grid - The 2D array representing the grid.
 * @param value - The value to search for.
 * @returns An array containing the row and column indices of the first matching cell, or an error if not found.
 */
export function gridFind(grid: number[][], value: number): number[] {
    for (let rowIndex = 0; rowIndex < grid.length; rowIndex++) {
        const columnIndex = grid[rowIndex].findIndex(cell => cell === value);
        if (columnIndex !== -1) {
            return [rowIndex, columnIndex];
        }
    }
    throw new Error("Value not found in the grid");
}
```