elastic/elasticsearch · error · IllegalArgumentException

vector dimensions incompatible: {}!= {}

Error message

vector dimensions incompatible: {}!= {}

What it means

Thrown by ESVectorUtil.dotProduct(float[] a, float[] b) when a.length != b.length. Vectors must have identical dimensionality for a dot product; a length mismatch is a programming/contract error, not a runtime data condition. IllegalArgumentException with both lengths in the message.

Source

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

        int dimension,
        int vectorLengthInBytes
    ) throws IOException {
        return SCORERS.newES93BinaryQuantizedVectorScorer(input, dimension, vectorLengthInBytes);
    }

    public static void bFloat16ToFloat(byte[] bfBytes, int bfOffset, float[] floats, int floatOffset, int floatCount, ByteOrder byteOrder) {
        IMPL.bFloat16ToFloat(bfBytes, bfOffset, floats, floatOffset, floatCount, byteOrder);
    }

    public static void floatToBFloat16(float[] floats, int floatOffset, byte[] bfBytes, int bfOffset, int floatCount, ByteOrder byteOrder) {
        assert floats.length - floatOffset >= floatCount;
        assert (bfBytes.length - bfOffset) >= floatCount * Short.BYTES;
        IMPL.floatToBFloat16(floats, floatOffset, bfBytes, bfOffset, floatCount, byteOrder);
    }

    public static float dotProduct(float[] a, float[] b) {
        if (a.length != b.length) {
            throw new IllegalArgumentException("vector dimensions incompatible: " + a.length + "!= " + b.length);
        }
        return IMPL.dotProduct(a, b);
    }

    /**
     * Dot product of the first {@code length} components of {@code a} and {@code b}.
     */
    public static float dotProduct(float[] a, float[] b, int length) {
        if (a.length != b.length) {
            throw new IllegalArgumentException("vector dimensions incompatible: " + a.length + "!= " + b.length);
        }
        Objects.checkFromIndexSize(0, length, a.length);
        return IMPL.dotProduct(a, b, 0, length);
    }

    /**
     * Dot product over {@code [offset, offset + length)}.
     */

View on GitHub (pinned to db6a809a66)

Solutions

  1. Verify both vectors have the same length before calling: if (a.length != b.length) reject with a domain-specific error.
  2. Ensure index mapping's dims and the query vector's dims come from the same model/config source.
  3. Reindex when the mapping's number_of_dims changes so stored vectors match the new dimensionality.
  4. Prefer the length-bounded overload dotProduct(a,b,length) when you want to operate on a prefix and can guarantee both arrays are at least that long.

Example fix

// before
float score = ESVectorUtil.dotProduct(queryVec, storedVec);

// after
if (queryVec.length != storedVec.length) {
    throw new IllegalArgumentException("query dims " + queryVec.length + " != stored dims " + storedVec.length);
}
float score = ESVectorUtil.dotProduct(queryVec, storedVec);
Defensive patterns

Strategy: validation

Validate before calling

if (a.length != b.length) {
    throw new IllegalArgumentException("dotProduct: a.length " + a.length + " != b.length " + b.length);
}
return ESVectorUtil.dotProduct(a, b);

Prevention

When it happens

Trigger: Passing two float[] of different lengths to dotProduct; one vector read from a stored field of dims N and the query vector built with dims M != N; a config change to dims that left cached/persisted vectors at the old length.

Common situations: Index mapping changed number_of_dims after documents were already indexed; query vector built with a different embedding model producing a different dimensionality than the indexed vectors; off-by-one slicing of a vector array.

Related errors


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