qdrant / qdrant/fastembed

Silent all-NaN embeddings when a model file is incompatible with the runtime (0.8.0 still ships the fp16 jina-de model fixed by #623)

Open
#688 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
3.2k
Forks
248
Avg merge
4d 8h
Merged PRs (30d)
4

Description

Summary

TextEmbedding can return vectors that are entirely NaN without raising, warning, or
logging anything. Downstream this is worse than a hard failure: cosine similarity becomes
NaN, ranking silently degenerates to input order, and a vector search appears to work
while returning meaningless results.

I ran into this through jinaai/jina-embeddings-v2-base-de, which is the case already fixed
on main by #623, but the silent-NaN behavior itself looks independent of that model.

Reproduction

from fastembed import TextEmbedding
import numpy as np

m = TextEmbedding(model_name="jinaai/jina-embeddings-v2-base-de")
v = np.array(list(m.embed(["Ein Testsatz."]))[0])
print(v.shape, np.isnan(v).sum())   # (768,) 768   -- no warning, no error

Environment: fastembed 0.8.0 (current PyPI), onnxruntime 1.29.0, providers
['AzureExecutionProvider', 'CPUExecutionProvider'], Python 3.12.12, Windows 11 x86_64.

Every one of the 768 components is NaN. Nothing on stderr, no exception, exit code 0.

Two separate points

1. The fp16 jina-de mapping is fixed on main but not released

#623 ("use original jina de model instead of fp16 due to onnxruntime up...") was merged
2026-04-15 and main now carries model_file="onnx/model.onnx". The newest PyPI release is
0.8.0 from 2026-03-23, so every pip install fastembed still gets the fp16 mapping and, on
onnxruntime >= 1.23, silently produces NaN. Is a release planned? This currently reaches
anyone selecting that model through a downstream package.

As a workaround on 0.8.0, onnx/model_quantized.onnx (int8, 154 MB) works correctly on CPU
and is both smaller and faster than the fp32 file main switched to — in my measurements ~5x
faster than bge-small-en-v1.5 on the same corpus. Possibly worth considering as the
mapping, though I have not compared int8 vs fp32 output quality.

2. The silent part is the more general problem

Independently of which file is mapped, a NaN result is not detectable by callers without
explicitly checking, and nothing in the docs suggests that is necessary. A cheap guard would
turn a silent data-corruption bug into an actionable error, for example checking the first
batch's output once per model load and raising something like
RuntimeError: model '<name>' produced non-finite embeddings with provider '<provider>'.

That would have surfaced #623's root cause immediately at the call site rather than as
unexplained ranking behavior downstream.

I am happy to open a PR for the guard if you think it is worth having and can point me at
where you would want the check to live.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the TextEmbedding model-loading and embed path, then inspect the model mapping changed by #623. Reproduce the all-NaN output with jinaai/jina-embeddings-v2-base-de and determine where a non-finite-output check belongs. Done means the incompatible model produces an actionable failure instead of silently returning NaN vectors.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
machine-learning
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.