didi/DoKit · error · IndexOutOfBoundsException

Index: " + index + ", Length: " + length

Error message

Index: " + index + ", Length: " + length

What it means

The non-null branch of realAdd validates the insertion index for a single element: it must satisfy 0 <= index <= length. Anything larger or negative would create an uninitialized gap in the new array, so it throws IndexOutOfBoundsException with the offending index and the actual length.

Solutions

  1. Clamp the index before the call: index = Math.max(0, Math.min(index, array.length))
  2. Convert binarySearch results correctly: int insertAt = -(pos) - 1;
  3. For append, use ArrayUtils.add(array, element) (end insertion) instead of computing index manually

Example fix

// before
int pos = Arrays.binarySearch(arr, key);
int[] out = ArrayUtils.add(arr, pos, value); // pos is negative when absent

// after
int pos = Arrays.binarySearch(arr, key);
int insertAt = pos >= 0 ? pos : -(pos) - 1;
int[] out = ArrayUtils.add(arr, insertAt, value);
Defensive patterns

Strategy: validation

Validate before calling

int safeIndex = Math.max(0, Math.min(index, array == null ? 0 : array.length));
int[] out = ArrayUtils.add(array, safeIndex, element);

Prevention

When it happens

Trigger: Calling ArrayUtils.add(array, index, element) with index > array.length or index < 0 — off-by-one appends (index = length + 1), negative results from binarySearch/indexOf used unchecked, or indices computed against a longer copy of the data.

Common situations: Using arrays.binarySearch's negative insertion points incorrectly (must be -(idx)-1). Cursor positions from UI (list scroll position) applied to a shorter backing array after a data refresh. Loop counters that overshoot by one.

Related errors


AI-assisted analysis of didi/DoKit@626827cddb (2026-08-14). Data as JSON: /api/errors/4186592f0fe4d95b. Report an issue: GitHub.

Appendix: source

Thrown at Android/dokit-util/src/main/java/com/didichuxing/doraemonkit/util/ArrayUtils.java:882

    @NonNull
    public static double[] add(@Nullable double[] array, int index, double element) {
        return (double[]) realAdd(array, index, element, Double.TYPE);
    }

    @NonNull
    private static Object realAdd(@Nullable Object array, int index, @Nullable Object element, Class clss) {
        if (array == null) {
            if (index != 0) {
                throw new IndexOutOfBoundsException("Index: " + index + ", Length: 0");
            }
            Object joinedArray = Array.newInstance(clss, 1);
            Array.set(joinedArray, 0, element);
            return joinedArray;
        }
        int length = Array.getLength(array);
        if (index > length || index < 0) {
            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
        }
        Object result = Array.newInstance(clss, length + 1);
        System.arraycopy(array, 0, result, 0, index);
        Array.set(result, index, element);
        if (index < length) {
            System.arraycopy(array, index, result, index + 1, length - index);
        }
        return result;
    }

    ///////////////////////////////////////////////////////////////////////////
    // remove
    ///////////////////////////////////////////////////////////////////////////

    /**
     * <p>Removes the element at the specified position from the specified array.
     * All subsequent elements are shifted to the left (substracts one from
     * their indices).</p>

View on GitHub (pinned to 626827cddb)