elastic/elasticsearch · error · IllegalArgumentException

vector dimensions incompatible: {}!= {} x {}

Error message

vector dimensions incompatible: {}!= {} x {}

What it means

Thrown by ipByteBinByte(byte[] q, byte[] d): inner product of a byte query against a 'bin'-packed byte document used by ES93 binary quantization scoring. Each document byte encodes B_QUERY (=4) query bytes, so the contract is q.length == d.length * B_QUERY (B_QUERY is 4, defined in ESVectorUtilSupport). The message embeds the actual q.length, B_QUERY and d.length so you can see which side is wrong.

Source

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

    /**
     * Bulk computation of cosine similarity from a byte query vector to four byte candidate vectors.
     */
    public static void cosineBulk(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.cosineBulk(q, v0, v1, v2, v3, distancesOffset, distances);
    }

    public static long ipByteBinByte(byte[] q, byte[] d) {
        if (q.length != d.length * B_QUERY) {
            throw new IllegalArgumentException("vector dimensions incompatible: " + q.length + "!= " + B_QUERY + " x " + d.length);
        }
        return IMPL.ipByteBinByte(q, d);
    }

    /**
     * Compute the inner product of two vectors, where the query vector is a byte vector and the document vector is a bit vector.
     * This will return the sum of the query vector values using the document vector as a mask.
     * When comparing the bits with the bytes, they are done in "big endian" order. For example, if the byte vector
     * is [1, 2, 3, 4, 5, 6, 7, 8] and the bit vector is [0b10000000], the inner product will be 1.0.
     * @param q the query vector
     * @param d the document vector
     * @return the inner product of the two vectors
     */
    public static int ipByteBit(byte[] q, byte[] d) {
        if (q.length != d.length * Byte.SIZE) {
            throw new IllegalArgumentException("vector dimensions incompatible: " + q.length + "!= " + Byte.SIZE + " x " + d.length);
        }
        return IMPL.ipByteBit(q, d);

View on GitHub (pinned to db6a809a66)

Solutions

  1. Verify the ES93 contract: the document must be bin-packed (1 bit per dim) and the query must be the 4-byte-per-64-dims quantized form, so q.length == d.length * 4.
  2. Log q.length, d.length and d.length * 4 at the call site to localize which side drifted.
  3. Ensure the same ES93 quantizer is used at index and query time; do not mix ES93 bin documents with plain int8 query encoding.
  4. If you cannot guarantee the 4x relation, route to a different scorer (e.g. ipByteBit or dotProduct) that matches your actual encodings.

Example fix

// before
long ip = ESVectorUtil.ipByteBinByte(qBytes, docBytes); // q.length != d.length * 4

// after
final int B_QUERY = 4;
if (qBytes.length != docBytes.length * B_QUERY) {
    throw new IllegalArgumentException("ipByteBinByte contract violated: q.length="
        + qBytes.length + " expected d.length*" + B_QUERY + "=" + (docBytes.length * B_QUERY));
}
long ip = ESVectorUtil.ipByteBinByte(qBytes, docBytes);
Defensive patterns

Strategy: validation

Validate before calling

final int B_QUERY = 4; // org.elasticsearch.simdvec.internal.vectorization.ESVectorUtilSupport.B_QUERY
if (q.length != d.length * B_QUERY) {
    throw new IllegalArgumentException("ipByteBinByte contract: q.length=" + q.length
        + " must equal d.length*B_QUERY=" + (d.length * B_QUERY));
}
long ip = ESVectorUtil.ipByteBinByte(q, d);

Try / catch

try {
    long ip = ESVectorUtil.ipByteBinByte(q, d);
} catch (IllegalArgumentException e) {
    throw new QueryException("ipByteBinByte: query not 4-byte-per-pack relative to bin document", e);
}

Prevention

When it happens

Trigger: Calling ipByteBinByte where the query byte length is not exactly 4 times the document byte length. Typical when the query vector was not 4-bit quantized to match the bin-packed document, or when the document was not bin-packed (e.g. a raw int8 vector was supplied instead of a binary-quantized one).

Common situations: ES93 binary quantization scorer wired to a non-binary document vector; query encoder changed (e.g. from ES93 to a plain int8 encoder) without re-routing the scorer; dimension configuration that doesn't satisfy discretize(dims,64) producing the expected packed length; stale segment from before a reindex.

Related errors


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