{"record":{"id":"18e67616ef35564b","repo":"BerriAI/litellm","slug":"valkey-semantic-cache-index-self-index-name-al","errorCode":null,"errorMessage":"Valkey semantic-cache index '{self.index_name}' already exists with embedding dimension {existing_dim}, but the configured embedding model produced dimension {dim}. Use a different valkey_semantic_cache_index_name or drop the existing index.","messagePattern":"Valkey semantic-cache index '(.+?)' already exists with embedding dimension (.+?), but the configured embedding model produced dimension (.+?)\\. Use a different valkey_semantic_cache_index_name or drop the existing index\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/caching/valkey_semantic_cache.py","lineNumber":155,"sourceCode":"\n    @staticmethod\n    def _extract_index_dim(info: dict) -> int | None:\n        # FT.INFO nests the vector field's \"dimensions\" one level inside its\n        # \"index\" block, so flatten each field descriptor a single level and\n        # scan for the dimensions marker.\n        for field in info.get(\"attributes\") or []:\n            if not isinstance(field, (list, tuple)):\n                continue\n            flat = [sub for item in field for sub in (item if isinstance(item, (list, tuple)) else [item])]\n            for i, marker in enumerate(flat):\n                if marker in (b\"dimensions\", \"dimensions\") and i + 1 < len(flat):\n                    return int(flat[i + 1])\n        return None\n\n    def _assert_dim_matches(self, info: dict, dim: int) -> None:\n        existing_dim: Final = self._extract_index_dim(info)\n        if existing_dim is not None and existing_dim != dim:\n            raise ValueError(\n                f\"Valkey semantic-cache index '{self.index_name}' already exists with \"\n                f\"embedding dimension {existing_dim}, but the configured embedding \"\n                f\"model produced dimension {dim}. Use a different \"\n                f\"valkey_semantic_cache_index_name or drop the existing index.\"\n            )\n\n    def _ensure_index_sync(self, dim: int) -> None:\n        if self._index_dim == dim:\n            return\n        try:\n            self.sync_client.ft(self.index_name).create_index(\n                self._index_schema(dim), definition=self._index_definition()\n            )\n        except Exception as exc:\n            if not self._is_index_exists_error(exc):\n                raise\n            self._assert_dim_matches(self.sync_client.ft(self.index_name).info(), dim)\n        self._index_dim = dim","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/caching/valkey_semantic_cache.py#L137-L173","documentation":"On first use the cache creates a valkey-search index whose vector dimension must match the embedding model. If an index with the same name already exists and its stored dimension differs from the dimension the currently configured model produces, _assert_dim_matches raises this ValueError. This protects against mixing embedding models in one index, which would make similarity search meaningless or error out at query time.","triggerScenarios":"Switching embedding_model (e.g. ada-002 dim 1536 → text-embedding-3-large dim 3072, or to a local model with a different dim) while keeping the same valkey_semantic_cache_index_name; or two deployments with different embedding models sharing one index name against the same Valkey.","commonSituations":"Upgrading the embedding model in production without rotating the cache index; staging and prod pointing at the same Valkey with different models; changing vector_size config after the index was created.","solutions":["Use a new index name per embedding model, e.g. valkey_semantic_cache_index_name='litellm-cache-3-large'","Or drop the existing index: valkey-cli FT.DROPINDEX <index_name> (data keys may need separate deletion) and let the cache recreate it with the new dimension","If you did not intend to change models, revert embedding_model to the one that created the index"],"exampleFix":"# before\ncache = ValkeySemanticCache(similarity_threshold=0.8,\n    embedding_model='text-embedding-3-large',  # dim 3072; index built for 1536\n    index_name='litellm-sem-cache')\n\n# after\ncache = ValkeySemanticCache(similarity_threshold=0.8,\n    embedding_model='text-embedding-3-large',\n    index_name='litellm-sem-cache-3large')  # fresh index for new dimension","handlingStrategy":"validation","validationCode":"EMBED_DIMS = {'text-embedding-ada-002': 1536, 'text-embedding-3-small': 1536, 'text-embedding-3-large': 3072}\n\ndef index_name_for(model: str, base: str = 'litellm-sem-cache') -> str:\n    # namespace the index by model so dimensions never collide\n    return f\"{base}-{model.replace('/', '-')}\"","typeGuard":null,"tryCatchPattern":"try:\n    cache = ValkeySemanticCache(**cfg)\nexcept ValueError as e:\n    if 'already exists with embedding dimension' in str(e):\n        raise ValueError('Rotate valkey_semantic_cache_index_name or FT.DROPINDEX the old index after embedding-model changes') from e\n    raise","preventionTips":["Include the embedding model name in the index name","Treat embedding-model changes as a cache-migration event: new index name, then expire the old one"],"tags":["valkey","semantic-cache","embedding","dimension-mismatch","index"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}