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.
Write — modules/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.
Read — engine.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
Summary
On 0.52.0 a freshly created cell carries no
vec:modeltag. The ingest path embeds untagged cells with the bundled singleton — now Nomic, truncated toSTORE_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 initruns to completion, prints "Flex is ready.", and every semantic query against the resulting cell raises.Reproduction
Also emitted at MCP startup, into
~/.flex/logs/mcp.errwhere it is easy to miss:Cause
vec:modelis 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.Write —
modules/claude_code/compile/worker.py:188:onnx/embed.py::encode()loadsmodels/nomic-v1.5-fp32/model.onnxatmatryoshka_dim=STORE_DIM(128). There is no MiniLM path left in that module.Read —
engine.py:199: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_opsdoes 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 fromcontentat native 768 and stampsvec:model+vec:serve_dim=256, after which ingest and serving agree.Hand-stamping
vec:model=nomic-v1.5-fp32also makes queries resolve to Nomic@128 and match the stored vectors, but then_encode_for_cellstarts routing new chunks through_resolve_ingest_targetat 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_targetunconditionally 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