You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
An operator requesting HNSW PQ compression can silently receive an unquantized segment: build_pq_for_index returns None on train/encode failure or bad shape, sealed_segment_from then attaches no codec, complete_build still returns true, and only a tracing::warn is emitted. stats().quantization becomes None — no error, no metric.
Steps to reproduce
Create an hnsw_pq index whose training cannot succeed (e.g. pq_m not dividing dim, or an empty live set), build it, then check stats(): quantization is None, complete_build returned true, log shows PQ training refused; segment stays unquantized (warn only).
Existing target: nodedb-vector/tests/vector_suite/cases/collection_pq_config.rs.
(static verification at the pin; runtime repro pending)
Expected behavior
If PQ init fails, build_pq_for_index / complete_build fail fast with a typed init error; the operator is told the codec did not build.
Actual behavior
Silent degradation to an unquantized graph; stats().quantization = None; only a warn log.
What actually happened? (severity facts)
Acknowledged/committed data was lost, corrupted, or silently wrong
The server crashed, hung, or failed to start
A security or isolation boundary was crossed
Core functionality is broken with no acceptable workaround
A workaround exists (check stats() after build or avoid hnsw_pq)
Proposed severity
SEV-3 — Medium: requested compression silently not applied; query results still correct, memory not as expected.
Reproducibility
Always — every attempt (deterministic on the failure conditions)
Last known-good version / commit (if a regression)
(unknown / not a regression)
Environment & logs
Linux x86_64; Verified by static code reading at the pin above; runtime reproduction pending.
Code references:
Reproduced on a released tag or current main build (pending) — code path verified at e235fe55c.
This is not a security vulnerability.
Additional evidence (origin/main @ e235fe55c)
What:build_pq_for_index returns None on invalid pq_m, no live vectors, or train/encode error. sealed_segment_from (build.rs:194-198) then attaches no codec, and complete_build returns true (build.rs:130). Only tracing::warn is emitted (quantize.rs:120,133). stats().quantization becomes None, not Pq.
Evidence: quotes above; test doc comment collection_pq_config.rs:8-12 claims an SQ8 fallback (wrong).
Impact: an operator requesting 8-16× PQ compression gets no error and no metric signal when the codec fails to train/encode; the query still returns results from the unquantized graph.
Fix (claim direction): make codec init strict. On HnswPq, return a typed init error from build_pq_for_index / complete_build instead of logging and returning None.
Prior-art:#50/PR [#65](fix(vector): resolve 7 correctness, memory-safety, and quantization bugs (#50) #65) fixed the original vector bug wave; the silent-failure residual is unraised. gh issue list --search "PQ quantization" --state open -> [].
Why: an operator requesting PQ compression gets no error and no metric when codec init fails; the segment silently stays unquantized (stats().quantization = None) and complete_build still returns true.
Steps to verify: build an hnsw_pq index whose training fails (pq_m not dividing dim, or empty live set) and assert a typed init error is returned (today: only tracing::warn + complete_build == true); existing test target nodedb-vector/tests/vector_suite/cases/collection_pq_config.rs.
Version / build tested against
origin/main @ e235fe5 (2026-09-29)
Deployment mode
Origin — single node (local)
Engine(s) involved
Vector
Summary
An operator requesting HNSW PQ compression can silently receive an unquantized segment:
build_pq_for_indexreturnsNoneon train/encode failure or bad shape,sealed_segment_fromthen attaches no codec,complete_buildstill returnstrue, and only atracing::warnis emitted.stats().quantizationbecomesNone— no error, no metric.Steps to reproduce
Create an
hnsw_pqindex whose training cannot succeed (e.g.pq_mnot dividing dim, or an empty live set), build it, then checkstats(): quantization isNone,complete_buildreturnedtrue, log showsPQ training refused; segment stays unquantized(warn only).Existing target:
nodedb-vector/tests/vector_suite/cases/collection_pq_config.rs.(static verification at the pin; runtime repro pending)
Expected behavior
If PQ init fails,
build_pq_for_index/complete_buildfail fast with a typed init error; the operator is told the codec did not build.Actual behavior
Silent degradation to an unquantized graph;
stats().quantization = None; only a warn log.What actually happened? (severity facts)
stats()after build or avoidhnsw_pq)Proposed severity
SEV-3 — Medium: requested compression silently not applied; query results still correct, memory not as expected.
Reproducibility
Always — every attempt (deterministic on the failure conditions)
Last known-good version / commit (if a regression)
(unknown / not a regression)
Environment & logs
Linux x86_64; Verified by static code reading at the pin above; runtime reproduction pending.
Code references:
Before submitting
mainbuild (pending) — code path verified ate235fe55c.Additional evidence (origin/main @
e235fe55c)build_pq_for_indexreturnsNoneon invalidpq_m, no live vectors, or train/encode error.sealed_segment_from(build.rs:194-198) then attaches no codec, andcomplete_buildreturnstrue(build.rs:130). Onlytracing::warnis emitted (quantize.rs:120,133).stats().quantizationbecomesNone, notPq.nodedb-vector/src/collection/build.rs:191-201;nodedb-vector/src/collection/quantize.rs:91-138;nodedb-vector/src/collection/stats.rs:40-46.collection_pq_config.rs:8-12claims an SQ8 fallback (wrong).HnswPq, return a typed init error frombuild_pq_for_index/complete_buildinstead of logging and returningNone.gh issue list --search "PQ quantization" --state open-> [].Why: an operator requesting PQ compression gets no error and no metric when codec init fails; the segment silently stays unquantized (
stats().quantization = None) andcomplete_buildstill returnstrue.Steps to verify: build an
hnsw_pqindex whose training fails (pq_mnot dividing dim, or empty live set) and assert a typed init error is returned (today: onlytracing::warn+complete_build == true); existing test targetnodedb-vector/tests/vector_suite/cases/collection_pq_config.rs.