elastic/elasticsearch · error · IllegalArgumentException

vector dimensions incompatible

Error message

vector dimensions incompatible

What it means

Thrown by squareDistanceBulk(byte[] q, byte[] v0, v1, v2, v3, int distancesOffset, float[] distances): bulk squared distance from one byte query to four byte candidates. The guard rejects when q.length differs from any of v0..v3.length. Note the message is plain 'vector dimensions incompatible' (no sizes embedded) — inspect lengths yourself to localize the offending candidate.

Source

Thrown at libs/simdvec/src/main/java/org/elasticsearch/simdvec/ESVectorUtil.java:294

        }
        return IMPL.squareDistance(a, b);
    }

    /** Returns the sum of squared differences of the two byte vectors over a sub-range. */
    public static float squareDistance(byte[] a, byte[] b, int offset, int length) {
        if (a.length != b.length) {
            throw new IllegalArgumentException("vector dimensions incompatible: " + a.length + "!= " + b.length);
        }
        Objects.checkFromIndexSize(offset, length, a.length);
        return IMPL.squareDistance(a, b, offset, length);
    }

    /**
     * Bulk computation of square distances from a byte query vector to four byte candidate vectors.
     */
    public static void squareDistanceBulk(byte[] q, byte[] v0, byte[] v1, byte[] v2, byte[] v3, int distancesOffset, float[] distances) {
        if (q.length != v0.length || q.length != v1.length || q.length != v2.length || q.length != v3.length) {
            throw new IllegalArgumentException("vector dimensions incompatible");
        }
        if (distances.length < 4) {
            throw new IllegalArgumentException("distances array must have length >= 4, but was: " + distances.length);
        }
        if (distancesOffset < 0 || distancesOffset > distances.length - 4) {
            throw new IllegalArgumentException("distancesOffset must be between 0 and distances.length - 4");
        }
        IMPL.squareDistanceBulk(q, 0, v0, v1, v2, v3, distancesOffset, distances, q.length);
    }

    /**
     * Bulk computation of square distances from a sub-range of a byte query vector to four byte candidate vectors.
     */
    public static void squareDistanceBulk(
        byte[] q,
        int qOffset,
        int length,
        byte[] v0,

View on GitHub (pinned to db6a809a66)

Solutions

  1. Before calling, assert q.length == v0.length == v1.length == v2.length == v3.length and log which one diverges.
  2. When padding candidate slots in graph traversal, pad with copies of a correctly-sized zero vector, not empty arrays.
  3. Validate decoded candidate length against the segment's quantized dims at read time.

Example fix

// before
ESVectorUtil.squareDistanceBulk(q, v0, v1, v2, v3, off, dist); // v2 wrong size

// after
for (byte[] v : new byte[][]{v0, v1, v2, v3}) {
    if (v.length != q.length) throw new IllegalArgumentException(
        "candidate length " + v.length + " != query " + q.length);
}
ESVectorUtil.squareDistanceBulk(q, v0, v1, v2, v3, off, dist);
Defensive patterns

Strategy: validation

Validate before calling

int n = q.length;
if (v0.length!=n || v1.length!=n || v2.length!=n || v3.length!=n) {
    throw new IllegalArgumentException("squareDistanceBulk candidate/query length mismatch: q=" + n
        + " v0=" + v0.length + " v1=" + v1.length + " v2=" + v2.length + " v3=" + v3.length);
}
ESVectorUtil.squareDistanceBulk(q, v0, v1, v2, v3, distancesOffset, distances);

Try / catch

try {
    ESVectorUtil.squareDistanceBulk(q, v0, v1, v2, v3, off, dist);
} catch (IllegalArgumentException e) {
    throw new QueryException("squareDistanceBulk bad args (dims or scratch)", e);
}

Prevention

When it happens

Trigger: Calling squareDistanceBulk where one of the four candidate byte vectors (v0..v3) has a different length from the query. Typical during HNSW graph traversal when a neighbor vector was decoded with a stale/shorter buffer, or when fewer than four real candidates are padded with differently-sized placeholders.

Common situations: Graph traversal padding short candidate slots with zero-length or differently-sized buffers; mixed quantization tiers across segments; a candidate loaded from a corrupted/shorter BytesRef; cross-version segment with different quantized dims.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/16ca7117ebf5cefd. Report an issue: GitHub.