Summary
The quantizer records use snake_case JSON names the server never reads. Weaviate parses these settings out of the config map by exact key, so everything except enabled, bits, segments, centroids and cache is silently dropped on write and null on read — on every index type, not just one. A user who sets a rescore limit never set one.
The mismatch
Java @SerializedName |
Server key |
Server source |
rescore_limit (BQ, SQ, RQ) |
rescoreLimit |
entities/vectorindex/hnsw/rq_config.go:31, sq_config.go:25, flat/config.go:147 |
training_limit (PQ, SQ) |
trainingLimit |
hnsw/pq_config.go:49, sq_config.go:24 |
bit_compression (PQ) |
bitCompression |
hnsw/pq_config.go:46 |
encoder_type + encoder_distribution (PQ) |
nested encoder: {type, distribution} |
hnsw/pq_config.go:50, encoderFromMap:97, encoderDistributionFromMap:117 |
The server reads them like this — a plain map lookup, no case folding, no snake_case fallback:
// entities/vectorindex/hnsw/rq_config.go
if err := common.OptionalIntFromMap(rqConfigMap, "rescoreLimit", func(v int) {
and returns them under the same names:
type RQConfig struct {
Enabled bool `json:"enabled"`
Bits int16 `json:"bits"`
RescoreLimit int `json:"rescoreLimit"`
}
So the break is symmetric: what the client sends is ignored, and what the server returns does not bind to the client's fields.
Affected fields
src/main/java/io/weaviate/client6/v1/api/collections/quantizers/:
RQ.rescoreLimit, BQ.rescoreLimit, SQ.rescoreLimit
SQ.trainingLimit, PQ.trainingLimit
PQ.bitCompression
PQ.encoderType, PQ.encoderDistribution — these are flat components in Java but a nested encoder object on the server, so they need a shape change rather than just a rename
enabled, bits, segments, centroids and cache already match and are unaffected.
Suggested fix
Rename the annotations to the camelCase keys, and give PQ's encoder its nested shape. No alternate values are needed: the snake_case spellings were never valid on the wire, so no stored config uses them.
Version
- java-client 6.3.1 (present since the quantizer records were introduced)
- Weaviate 1.39.0
Found while investigating #606, which is unfixable in practice without this: locating a nested rq still yields a null rescoreLimit.
Summary
The quantizer records use snake_case JSON names the server never reads. Weaviate parses these settings out of the config map by exact key, so everything except
enabled,bits,segments,centroidsandcacheis silently dropped on write and null on read — on every index type, not just one. A user who sets a rescore limit never set one.The mismatch
@SerializedNamerescore_limit(BQ, SQ, RQ)rescoreLimitentities/vectorindex/hnsw/rq_config.go:31,sq_config.go:25,flat/config.go:147training_limit(PQ, SQ)trainingLimithnsw/pq_config.go:49,sq_config.go:24bit_compression(PQ)bitCompressionhnsw/pq_config.go:46encoder_type+encoder_distribution(PQ)encoder: {type, distribution}hnsw/pq_config.go:50,encoderFromMap:97,encoderDistributionFromMap:117The server reads them like this — a plain map lookup, no case folding, no snake_case fallback:
and returns them under the same names:
So the break is symmetric: what the client sends is ignored, and what the server returns does not bind to the client's fields.
Affected fields
src/main/java/io/weaviate/client6/v1/api/collections/quantizers/:RQ.rescoreLimit,BQ.rescoreLimit,SQ.rescoreLimitSQ.trainingLimit,PQ.trainingLimitPQ.bitCompressionPQ.encoderType,PQ.encoderDistribution— these are flat components in Java but a nestedencoderobject on the server, so they need a shape change rather than just a renameenabled,bits,segments,centroidsandcachealready match and are unaffected.Suggested fix
Rename the annotations to the camelCase keys, and give PQ's encoder its nested shape. No
alternatevalues are needed: the snake_case spellings were never valid on the wire, so no stored config uses them.Version
Found while investigating #606, which is unfixable in practice without this: locating a nested
rqstill yields a nullrescoreLimit.