slint-ui/slint · error · RangeError

row index is out of bounds

Error message

row index ${index} is out of bounds

What it means

RangeArrayModel.removeRow validates the requested index against the current array length before deleting; this RangeError is the guard firing. It means the caller passed an index outside 0..rowCount()-1 — typically a stale index captured before a prior removal shrank the model, an off-by-one from using rowCount() itself, or a negative value. The model's backing array is untouched when this throws.

Solutions

  1. Check 0 <= index < model.rowCount() before calling removeRow.
  2. Re-fetch rowCount after each removal instead of caching indices.
  3. Clamp the index: Math.min(Math.max(index,0), rowCount()-1) when appropriate.

Example fix

// before
model.removeRow(selectedIndex);
// after
if (selectedIndex >= 0 && selectedIndex < model.rowCount()) model.removeRow(selectedIndex);
Defensive patterns

Strategy: validation

Validate before calling

if (!Number.isInteger(index) || index < 0 || index >= model.rowCount()) {
  throw new RangeError(`cannot remove row ${index}; rowCount=${model.rowCount()}`);
}

Type guard

const canRemoveAt = (m: { rowCount(): number }, i: number): boolean =>
  Number.isInteger(i) && i >= 0 && i < m.rowCount();

Try / catch

try {
  model.removeRow(index);
} catch (e) {
  if (e instanceof RangeError) {
    console.warn(`skipping removal: ${e.message}`);
  } else throw e;
}

Prevention

When it happens

Trigger: removeRow called with a negative index, an index equal to or larger than rowCount, or after the array was shrunk by another removal.

Common situations: Off-by-one in delete loops, stale indices kept after previous removals, race between UI row index and array contents.

Related errors


AI-assisted analysis of slint-ui/slint@bb937076de (2026-09-16). Data as JSON: /api/errors/d0a27c4298ddd5cd. Report an issue: GitHub.

Appendix: source

Thrown at api/node/typescript/models.ts:268

    /**
     * Stores the given data on the given row index and notifies run-time about the changed row.
     * @param row index in range 0..(rowCount() - 1).
     * @param data new data item to store on the given row index
     */
    setRowData(row: number, data: T) {
        this.#array[row] = data;
        this.notifyRowDataChanged(row);
    }

    /**
     * Remove a row from the array backing the model and notifies run-time about the removed row.
     * Throws a RangeError when the index is out of bounds.
     * @param index index of the row to remove.
     */
    removeRow(index: number): void {
        if (index < 0 || index >= this.#array.length) {
            throw new RangeError(`row index ${index} is out of bounds`);
        }
        this.remove(index, 1);
    }

    /**
     * Insert a new row into the array backing the model at the specified index and notifies run-time about the added row.
     * Throws a RangeError when the index is out of bounds.
     * @param index index at which to insert the new row.
     * @param data data item to store in the new row.
     */
    insertRow(index: number, data: T): void {
        if (index < 0 || index > this.#array.length) {
            throw new RangeError(`row index ${index} is out of bounds`);
        }
        this.splice(index, 0, data);
    }

    /**

View on GitHub (pinned to bb937076de)