Skip to content

Vector: HNSW+PQ init failure is silent — segment stays unquantized, stats() shows None with no error #395

Description

@EnRaiha

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_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:

  • (see prior-art line below)

Before submitting


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.
  • Where: nodedb-vector/src/collection/build.rs:191-201; nodedb-vector/src/collection/quantize.rs:91-138; nodedb-vector/src/collection/stats.rs:40-46.
  • 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions