Skip to content

FastEmbed cache defaults to /tmp/fastembed_cache — breaks MCP in sandboxed runtimes (Codex, ephemeral /tmp) #741

@groksrc

Description

@groksrc

Summary

When semantic_embedding_cache_dir is unset (the default), FastEmbed falls back to its own default of <system temp dir>/fastembed_cache — on Linux this resolves to /tmp/fastembed_cache. In sandboxed MCP runtimes like Codex CLI, /tmp is ephemeral (wiped between invocations) or otherwise unreliable, so the ONNX model either fails to download or disappears between runs, and every semantic search raises ONNXRuntimeError : NO_SUCHFILE.

Stack trace

# Search Failed

Error searching for 'FrameAnnotation video_id object_id':
    [ONNXRuntimeError] : 3 : NO_SUCHFILE : Load model from
    /tmp/fastembed_cache/models--qdrant--bge-small-en-v1.5-onnx-q/
    snapshots/52398278842ec682c6f32300af41344b1c0b0bb2/
    model_optimized.onnx failed: Load model
    /tmp/fastembed_cache/models--qdrant--bge-small-en-v1.5-onnx-q/
    snapshots/523...

Root cause

FastEmbedEmbeddingProvider only passes cache_dir to TextEmbedding(...) when semantic_embedding_cache_dir is explicitly set (see src/basic_memory/repository/fastembed_provider.py:75-85). When it's None, FastEmbed's own default kicks in:

cache_dir (str, optional): The path to the cache directory. Can be set using the FASTEMBED_CACHE_PATH env variable. Defaults to fastembed_cache in the system's temp directory.
fastembed/text/onnx_embedding.py

Basic Memory's config default:

# src/basic_memory/config.py
semantic_embedding_cache_dir: str | None = Field(
    default=None,
    description=\"Optional cache directory for FastEmbed model artifacts.\",
)

Why this surfaces now

Semantic search has been default-on for a while, but FastEmbed was only loaded lazily on first semantic query, so users whose environments didn't tolerate /tmp/fastembed_cache could silently avoid it. Recent changes make FastEmbed load much more eagerly:

Combined with a runtime (Codex) that wipes /tmp between sessions, the model directory disappears and every subsequent ONNX load fails with NO_SUCHFILE.

Proposed fix

Default semantic_embedding_cache_dir to a stable, user-writable path under the Basic Memory config/data dir instead of relying on the system temp dir. Something like:

def _default_fastembed_cache_dir() -> str:
    # Stable across runs, user-writable, honors XDG on Linux.
    return str(Path(platformdirs.user_cache_dir(\"basic-memory\")) / \"fastembed\")

semantic_embedding_cache_dir: str = Field(
    default_factory=_default_fastembed_cache_dir,
    description=\"Cache directory for FastEmbed model artifacts.\",
)

Alternative / additional hardening:

  • Respect FASTEMBED_CACHE_PATH if set in the environment (FastEmbed already does, but we should document it).
  • At startup, if the configured cache dir isn't writable, log a clear warning and fall back to ~/.basic-memory/fastembed_cache.

Workarounds

  • Set FASTEMBED_CACHE_PATH=~/.cache/fastembed in the MCP server's env.
  • Set semantic_embedding_cache_dir in ~/.basic-memory/config.json to a stable user-writable path.
  • As a last resort, disable semantic search: BASIC_MEMORY_SEMANTIC_SEARCH_ENABLED=false.

Reproduction

  1. Start basic-memory mcp in a runtime where /tmp is ephemeral (Codex CLI sandbox, or simply rm -rf /tmp/fastembed_cache between runs on Linux).
  2. Trigger any sync or semantic search.
  3. Observe ONNXRuntimeError : NO_SUCHFILE referencing /tmp/fastembed_cache/....

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions