Skip to content

Untagged cells are embedded with Nomic but served as MiniLM — semantic search fails on every fresh 0.52 install #4

Description

@alecmarcus

Summary

On 0.52.0 a freshly created cell carries no vec:model tag. The ingest path embeds untagged cells with the bundled singleton — now Nomic, truncated to STORE_DIM=128 — while the serving path interprets untagged as MiniLM and fail-closes because the pre-0.52 MiniLM model is no longer installed.

Net effect: flex init runs to completion, prints "Flex is ready.", and every semantic query against the resulting cell raises.

Reproduction

curl -sSL https://getflex.dev/install.sh | bash -s -- claude-code
flex core search --cell claude_code "SELECT v.id, v.score FROM vec_ops('similar:anything') v LIMIT 3"
RuntimeError: legacy minilm cell requires its retained pre-0.52 model; the model is not installed
  flex/engine.py:204 in _query_embedder_for

Also emitted at MCP startup, into ~/.flex/logs/mcp.err where it is easy to miss:

[flex-mcp]   claude_code: legacy minilm cell requires its retained pre-0.52 model; the model is not installed
[flex-mcp] Background warmup finished with 1 error(s) (1 cached)

Cause

vec:model is written in exactly one place in the package — retrieve/embeddings.py:18 (set_active_model). Nothing on the init path calls it, so new cells are untagged.

Writemodules/claude_code/compile/worker.py:188:

tag = _cell_tag(conn)
if tag in (None, 'minilm'):
    return encode(texts)          # legacy fast path, bypasses _resolve_ingest_target

onnx/embed.py::encode() loads models/nomic-v1.5-fp32/model.onnx at matryoshka_dim=STORE_DIM (128). There is no MiniLM path left in that module.

Readengine.py:199:

elif tag not in (None, 'minilm'):
    raise ValueError(...)
# Only 'minilm' or absent use the retained pre-0.52 space.
if not _LEGACY_MODEL_PATH.exists():
    raise RuntimeError("legacy minilm cell requires its retained pre-0.52 model")

So untagged means "whatever singleton ships today" to the writer and "MiniLM specifically" to the reader. Those agreed until 0.52 swapped the bundled model and dropped MiniLM from the installer; only the reader was updated to fail closed.

Impact

My cell holds 126,893 Nomic@128 vectors that nothing in the package will read. FTS/keyword retrieval works; vec_ops does not. The installer reports success, and the MCP server is registered and serving.

Worth noting the fail-closed check is doing exactly the right thing here — both spaces are 128 wide, so if MiniLM were still installed this would be silent garbage ranking rather than an exception.

Workaround

flex reembed <cell> re-encodes from content at native 768 and stamps vec:model + vec:serve_dim=256, after which ingest and serving agree.

Hand-stamping vec:model=nomic-v1.5-fp32 also makes queries resolve to Nomic@128 and match the stored vectors, but then _encode_for_cell starts routing new chunks through _resolve_ingest_target at native 768 — producing precisely the mixed-width cell its own docstring warns about.

Suggestion

Have init stamp the tag it actually embedded with, or route ingest through _resolve_ingest_target unconditionally so the "never diverges from serving" guarantee in its docstring holds for untagged cells too.

Environment

getflex 0.52.0 · macOS (Darwin 25.5.0, arm64) · Python 3.14.3 · module claude-code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions