Mintplex-Labs/anything-llm · error · Error

ChromaDB::Invalid Heartbeat received - is the instance onlin

Error message

ChromaDB::Invalid Heartbeat received - is the instance online?

What it means

During ChromaVectorDb.connect(), the client sends a heartbeat() to the Chroma server; a falsy response throws this error. It fires before credentials are exercised for data operations, so it is the first signal that CHROMA_ENDPOINT is wrong or the Chroma server process is not reachable/healthy.

Source

Thrown at server/utils/vectorDbProviders/chroma/index.js:87

      throw new Error("Chroma::Invalid ENV settings");

    const client = new ChromaClient({
      path: process.env.CHROMA_ENDPOINT, // if not set will fallback to localhost:8000
      ...(!!process.env.CHROMA_API_HEADER && !!process.env.CHROMA_API_KEY
        ? {
            fetchOptions: {
              headers: parseAuthHeader(
                process.env.CHROMA_API_HEADER || "X-Api-Key",
                process.env.CHROMA_API_KEY
              ),
            },
          }
        : {}),
    });

    const isAlive = await client.heartbeat();
    if (!isAlive)
      throw new Error(
        "ChromaDB::Invalid Heartbeat received - is the instance online?"
      );
    return { client };
  }

  async heartbeat() {
    const { client } = await this.connect();
    return { heartbeat: await client.heartbeat() };
  }

  async totalVectors() {
    const { client } = await this.connect();
    const collections = await client.listCollections();
    var totalVectors = 0;
    for (const collectionObj of collections) {
      const collection = await client
        .getCollection({ name: collectionObj.name })
        .catch(() => null);

View on GitHub (pinned to 20f6d3546c)

Solutions

  1. Start or restart Chroma: docker run -p 8000:8000 chromadb/chroma (or your compose service).
  2. Fix CHROMA_ENDPOINT to the address actually reachable from the AnythingLLM process (http://chroma:8000 inside docker-compose, not localhost).
  3. Verify with curl: curl http://<host>:8000/api/v2/heartbeat should return a nanosecond timestamp.
  4. If auth is on, set both CHROMA_API_HEADER and CHROMA_API_KEY - a missing pair sends no auth and proxies may 401 the heartbeat.

Example fix

# before (.env)
VECTOR_DB=chroma
# CHROMA_ENDPOINT unset -> defaults to localhost:8000, nothing there

# after (.env)
VECTOR_DB=chroma
CHROMA_ENDPOINT=http://chroma:8000
CHROMA_API_HEADER=X-Api-Key
CHROMA_API_KEY=<secret>
Defensive patterns

Strategy: retry

Validate before calling

async function chromaReachable(endpoint) {
  try {
    const res = await fetch(`${endpoint}/api/v2/heartbeat`, { signal: AbortSignal.timeout(3000) });
    return res.ok;
  } catch { return false; }
}
if (!(await chromaReachable(process.env.CHROMA_ENDPOINT))) throw new Error('Chroma unreachable');

Try / catch

try {
  await vectorDb.connect();
} catch (e) {
  if (/Invalid Heartbeat/i.test(e.message)) {
    await sleep(2000); // container may still be starting
    return vectorDb.connect();
  }
  throw e;
}

Prevention

When it happens

Trigger: Any vector operation (connect, totalVectors, addDocumentToNamespace, namespace-stats) when Chroma is down, the endpoint URL/port is wrong, a reverse proxy strips the /api/v2 heartbeat route, or authentication headers are rejected so heartbeat returns a non-OK response.

Common situations: chroma server/container not started or crashed; CHROMA_ENDPOINT left at default localhost:8000 in docker where the service name should be used; Chroma v0.4+ client/server routing changes behind a proxy; firewall blocking the port.

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@20f6d3546c (2026-08-18). Data as JSON: /api/errors/45426be2853ed4ed. Report an issue: GitHub.