You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by be...@apache.org on 2026/06/01 17:49:48 UTC
(lucene) branch branch_10x updated: Validate zero vectors in setVectorValue() for cosine similarity fields (#16098)
This is an automated email from the ASF dual-hosted git repository.
benwtrent pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/lucene.git
The following commit(s) were added to refs/heads/branch_10x by this push:
new ea5d96a462f Validate zero vectors in setVectorValue() for cosine similarity fields (#16098)
ea5d96a462f is described below
commit ea5d96a462f92ffec96d0ad04460f5b55c8a5a4b
Author: Prithvi S <pr...@gmail.com>
AuthorDate: Mon Jun 1 23:10:45 2026 +0530
Validate zero vectors in setVectorValue() for cosine similarity fields (#16098)
---
lucene/CHANGES.txt | 2 +
.../apache/lucene/document/KnnByteVectorField.java | 4 ++
.../lucene/document/KnnFloatVectorField.java | 6 ++-
.../java/org/apache/lucene/util/VectorUtil.java | 2 +-
.../test/org/apache/lucene/document/TestField.java | 45 ++++++++++++++++++++++
5 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index ad2da50dd6d..50d1a3ec14a 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -251,6 +251,8 @@ Bug Fixes
* GITHUB#15878: Fix LargeNumHitsTopDocsCollector not handling requested hit count correctly (Binlong Gao)
+* GITHUB#16098: Validate zero vectors in setVectorValue() for cosine similarity fields. (Prithvi S)
+
* GITHUB#16046: Fix double-counting of underlying Automaton in CompiledAutomaton#ramBytesUsed. (Eugene Rizhkov)
* GITHUB#15901: Fix undercounting of RAM used by vectors buffered in in-memory segments.
diff --git a/lucene/core/src/java/org/apache/lucene/document/KnnByteVectorField.java b/lucene/core/src/java/org/apache/lucene/document/KnnByteVectorField.java
index 570ef43c56f..fd69b3ba3ec 100644
--- a/lucene/core/src/java/org/apache/lucene/document/KnnByteVectorField.java
+++ b/lucene/core/src/java/org/apache/lucene/document/KnnByteVectorField.java
@@ -168,6 +168,10 @@ public class KnnByteVectorField extends Field {
throw new IllegalArgumentException(
"value length " + value.length + " must match field dimension " + type.vectorDimension());
}
+ if (type.vectorSimilarityFunction() == VectorSimilarityFunction.COSINE
+ && VectorUtil.isZeroVector(value)) {
+ throw new IllegalArgumentException("zero vector not allowed with cosine similarity function");
+ }
fieldsData = value;
}
}
diff --git a/lucene/core/src/java/org/apache/lucene/document/KnnFloatVectorField.java b/lucene/core/src/java/org/apache/lucene/document/KnnFloatVectorField.java
index dcdb8a1735d..259b3576226 100644
--- a/lucene/core/src/java/org/apache/lucene/document/KnnFloatVectorField.java
+++ b/lucene/core/src/java/org/apache/lucene/document/KnnFloatVectorField.java
@@ -169,6 +169,10 @@ public class KnnFloatVectorField extends Field {
throw new IllegalArgumentException(
"value length " + value.length + " must match field dimension " + type.vectorDimension());
}
- fieldsData = value;
+ if (type.vectorSimilarityFunction() == VectorSimilarityFunction.COSINE
+ && VectorUtil.isZeroVector(value)) {
+ throw new IllegalArgumentException("zero vector not allowed with cosine similarity function");
+ }
+ fieldsData = VectorUtil.checkFinite(value);
}
}
diff --git a/lucene/core/src/java/org/apache/lucene/util/VectorUtil.java b/lucene/core/src/java/org/apache/lucene/util/VectorUtil.java
index a526363b679..cf9eb759bc8 100644
--- a/lucene/core/src/java/org/apache/lucene/util/VectorUtil.java
+++ b/lucene/core/src/java/org/apache/lucene/util/VectorUtil.java
@@ -465,7 +465,7 @@ public final class VectorUtil {
/** Returns true if all dimensions of provided vector are zero, false otherwise. */
public static boolean isZeroVector(byte[] v) {
- for (float value : v) {
+ for (byte value : v) {
if (value != 0) {
return false;
}
diff --git a/lucene/core/src/test/org/apache/lucene/document/TestField.java b/lucene/core/src/test/org/apache/lucene/document/TestField.java
index 8eeecaf0fa6..116e880dbfd 100644
--- a/lucene/core/src/test/org/apache/lucene/document/TestField.java
+++ b/lucene/core/src/test/org/apache/lucene/document/TestField.java
@@ -765,6 +765,51 @@ public class TestField extends LuceneTestCase {
assertTrue(zeroError.getMessage().contains("zero vector not allowed"));
}
+ public void testKnnFieldSetVectorValueZeroVectors() throws Exception {
+ // Float vector field: setVectorValue with zero vector on COSINE field should fail
+ KnnFloatVectorField floatField =
+ new KnnFloatVectorField(
+ "knnFloats", new float[] {1, 2, 3, 4, 5}, VectorSimilarityFunction.COSINE);
+ IllegalArgumentException zeroError =
+ expectThrows(IllegalArgumentException.class, () -> floatField.setVectorValue(new float[5]));
+ assertTrue(zeroError.getMessage().contains("zero vector not allowed"));
+
+ // Non-zero setVectorValue should succeed
+ floatField.setVectorValue(new float[] {5, 4, 3, 2, 1});
+
+ // Byte vector field: setVectorValue with zero vector on COSINE field should fail
+ KnnByteVectorField byteField =
+ new KnnByteVectorField(
+ "knnBytes", new byte[] {1, 2, 3, 4, 5}, VectorSimilarityFunction.COSINE);
+ zeroError =
+ expectThrows(IllegalArgumentException.class, () -> byteField.setVectorValue(new byte[5]));
+ assertTrue(zeroError.getMessage().contains("zero vector not allowed"));
+
+ // Non-zero setVectorValue should succeed
+ byteField.setVectorValue(new byte[] {5, 4, 3, 2, 1});
+
+ // EUCLIDEAN fields should allow zero vectors via setVectorValue
+ KnnFloatVectorField euclideanFloatField =
+ new KnnFloatVectorField(
+ "knnFloatsEuc", new float[] {1, 2, 3, 4, 5}, VectorSimilarityFunction.EUCLIDEAN);
+ euclideanFloatField.setVectorValue(new float[5]);
+
+ KnnByteVectorField euclideanByteField =
+ new KnnByteVectorField(
+ "knnBytesEuc", new byte[] {1, 2, 3, 4, 5}, VectorSimilarityFunction.EUCLIDEAN);
+ euclideanByteField.setVectorValue(new byte[5]);
+
+ // Float vector field: setVectorValue with NaN should fail
+ KnnFloatVectorField nanField =
+ new KnnFloatVectorField(
+ "knnFloatsNaN", new float[] {1, 2, 3, 4, 5}, VectorSimilarityFunction.EUCLIDEAN);
+ IllegalArgumentException nanError =
+ expectThrows(
+ IllegalArgumentException.class,
+ () -> nanField.setVectorValue(new float[] {1, 2, Float.NaN, 4, 5}));
+ assertTrue(nanError.getMessage().contains("non-finite"));
+ }
+
private void trySetByteValue(Field f) {
expectThrows(
IllegalArgumentException.class,