Skip to content

Windows: Chroma spawn routes >/< dependency specifiers through cmd.exe /c, breaking semantic search (Connection closed -> FTS5 fallback) #2954

Description

@FadiBadr86

Summary

On Windows, semantic search silently degrades to FTS5 keyword search. Every Chroma sync and every search logs MCP error -32000: Connection closed, and the Chroma store is never populated.

Root cause

The worker spawns chroma-mcp through the command shell:

cmd.exe /c uvx --python 3.13 --with onnxruntime>=1.20 --with protobuf<7 chroma-mcp==0.2.6 --client-type persistent --data-dir ...\chroma

The dependency specifiers contain > and <, which cmd.exe interprets as redirection operators:

  • --with protobuf<7 makes cmd read stdin from a file named 7The system cannot find the file specified → child exits with code 1.
  • --with onnxruntime>=1.20 redirects stdout to a file.

The uvx command never runs, the child exits in ~200–500 ms, and the stdio transport reports Connection closed. The per-arg quoter (regex /[<>|&^()]/, wraps the arg in double quotes) does not survive node-spawn → cmd.exe re-parse, so it does not prevent the redirection.

Relevant code (worker-service.cjs, chroma manager connect):

let n = process.platform === "win32",
    s = n ? process.env.ComSpec || "cmd.exe" : "uvx",
    i = n ? ["/c", "uvx", ...e.map(quoteArg)] : e;

Proof

  • Spawning the same uvx with the identical args directly (no cmd.exe) succeeds: initialize returns, chroma_list_collections returns __NO_COLLECTIONS_FOUND__, and the server stays alive. The binary, the data dir, and the handshake are all healthy.
  • The same args via cmd.exe /c uvx ... exit code 1 with The system cannot find the file specified (the <7 input redirect from a nonexistent file 7).

Fix that works

Spawn the resolved uvx.exe path directly instead of through cmd.exe /c, so arguments pass verbatim through CreateProcess argv with no shell metacharacter parsing — the same path that already works on macOS/Linux. After this change on an affected machine: the deep probe reports healthy / connected / round-trip succeeded, chroma.sqlite3 grows from ~188 KB to ~97 MB, segment directories appear, and semantic search returns ranked results with no FTS5 fallback warning.

Caret-escaping the metacharacters for cmd.exe, or pinning the deps to metacharacter-free specifiers, would also work, but bypassing the shell is the cleanest and matches the non-Windows code path.

Environment

  • Windows Server 2025 (10.0.26100), runner: bun
  • claude-mem 13.4.x
  • uv/uvx installed at %USERPROFILE%\.local\bin
  • chroma-mcp 0.2.6, chromadb server 1.6.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions