elastic/elasticsearch · error · IllegalArgumentException
distances array must have length >= 4, but was: {}
Error message
distances array must have length >= 4, but was: {} What it means
Thrown by squareDistanceBulk (byte, offset variant) when distances.length < 4: the bulk operation writes four floats (one per candidate) into the output array, so it needs at least four slots beyond the offset. The message reports the actual length so you can see how short it is.
Source
Thrown at libs/simdvec/src/main/java/org/elasticsearch/simdvec/ESVectorUtil.java:297
/** 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,
byte[] v1,
byte[] v2,
byte[] v3,View on GitHub (pinned to db6a809a66)
Solutions
- Allocate the distances buffer as new float[4] (or larger if you intend to also use distancesOffset).
- Centralize scratch-buffer allocation in a factory that guarantees minimum length 4 for bulk scorers.
- Assert distances.length >= 4 once when the scorer is constructed, not on every call.
Example fix
// before float[] dist = new float[3]; ESVectorUtil.squareDistanceBulk(q, v0, v1, v2, v3, 0, dist); // after float[] dist = new float[4]; ESVectorUtil.squareDistanceBulk(q, v0, v1, v2, v3, 0, dist);
Defensive patterns
Strategy: validation
Validate before calling
if (distances.length < 4) {
throw new IllegalArgumentException("squareDistanceBulk needs distances.length >= 4, got " + distances.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 distances buffer too small", e);
} Prevention
- Allocate the bulk scratch as new float[4] (or larger when using distancesOffset).
- Centralize bulk scratch allocation so the minimum-4 invariant is enforced once.
- Do not share a single-result scratch buffer with the bulk code path.
When it happens
Trigger: Calling squareDistanceBulk with a float[] distances argument whose length is less than 4. Common when reusing a smaller scratch buffer from a non-bulk code path or allocating dist with the wrong constant.
Common situations: Scratch buffer sized for a single result (length 1) and reused for a bulk call; allocation typo (e.g. new float[3]); buffer pool that hands out arrays of varying capacity.
Related errors
- distancesOffset must be between 0 and distances.length - 4
- distances array must have length 4, but was: {}
- vector dimensions incompatible
- vector dimensions incompatible: {}!= {} x {}
- Pitch needs to be at least {}
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/cae8753e412a0fea.
Report an issue: GitHub.