{"record":{"id":"63c8ce1c1e2f1759","repo":"headroomlabs-ai/headroom","slug":"embeddingscorer-requires-fastembed-install-with","errorCode":null,"errorMessage":"EmbeddingScorer requires fastembed. Install with: pip install headroom[relevance]","messagePattern":"EmbeddingScorer requires fastembed\\. Install with: pip install headroom\\[relevance\\]","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"headroom/relevance/embedding.py","lineNumber":167,"sourceCode":"        \"\"\"\n        try:\n            import fastembed  # noqa: F401\n\n            return True\n        except ImportError:\n            return False\n\n    def _get_model(self) -> TextEmbedding:\n        \"\"\"Get or load the fastembed text embedding model.\n\n        Returns:\n            Loaded TextEmbedding model.\n\n        Raises:\n            RuntimeError: If fastembed is not installed.\n        \"\"\"\n        if not self.is_available():\n            raise RuntimeError(\n                \"EmbeddingScorer requires fastembed. Install with: pip install headroom[relevance]\"\n            )\n\n        if self._model is None:\n            from fastembed import TextEmbedding\n\n            revision = _pinned_revision(self.model_name)\n            if revision is not None:\n                # fastembed forwards **kwargs to snapshot_download(revision=...).\n                self._model = TextEmbedding(model_name=self.model_name, revision=revision)\n            else:\n                self._model = TextEmbedding(model_name=self.model_name)\n        return self._model\n\n    def _encode(self, texts: list[str]):\n        \"\"\"Encode texts to embeddings via fastembed.\n\n        fastembed's `embed` returns an iterator yielding numpy arrays","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/relevance/embedding.py#L149-L185","documentation":"Raised by EmbeddingScorer._get_model() when the fastembed package is not installed. The scorer guards model loading behind is_available() so the constructor succeeds even in installs without fastembed, and this error appears only when you actually try to load the model.","triggerScenarios":"Constructing an EmbeddingScorer directly (bypassing create_scorer's check) and calling any method that loads the model, in an environment without fastembed.","commonSituations":"Instantiating EmbeddingScorer directly instead of via create_scorer(); pruning 'unused' packages from a Docker layer; deploying to a runtime environment different from the build one.","solutions":["Install the extra: pip install 'headroom[relevance]'.","Construct scorers via create_scorer('embedding') so availability is checked up front with a clearer error.","Prefer the bm25 tier when embeddings are not required."],"exampleFix":"# before\nscorer = EmbeddingScorer()\nvec = next(scorer._get_model().embed(['hi']))\n\n# after\n# pip install 'headroom[relevance]'\nfrom headroom.relevance import create_scorer\nscorer = create_scorer('embedding')","handlingStrategy":"fallback","validationCode":"from headroom.relevance import EmbeddingScorer, create_scorer\n\ndef build_scorer(**kw):\n    tier = 'embedding' if EmbeddingScorer.is_available() else 'bm25'\n    return create_scorer(tier, **kw)","typeGuard":"from headroom.relevance import EmbeddingScorer\n\ndef embedding_model_available() -> bool:\n    return bool(EmbeddingScorer.is_available())","tryCatchPattern":"try:\n    scorer = create_scorer('embedding', **kwargs)\nexcept RuntimeError as e:\n    if 'fastembed' in str(e):\n        scorer = create_scorer('bm25', **kwargs)\n    else:\n        raise","preventionTips":["Always construct scorers through create_scorer(); it checks availability before building.","Prefer is_available() probes at startup over catching lazy-load failures per request.","Keep the [relevance] extra in lockstep with headroom upgrades."],"tags":["dependencies","optional-feature","fastembed","lazy-import"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}