chroma-core/chroma · error · ChromaConnectionError

Failed to connect to chromadb. Make sure your server is runn

Error message

Failed to connect to chromadb. Make sure your server is running and try again. If you are running from a browser, make sure that your chromadb instance is configured to allow requests from the current origin using the CHROMA_SERVER_CORS_ALLOW_ORIGINS environment variable.

What it means

Aggregate.from_dict() (operator.py:1409-1410) rejects any payload that is not a dict with a TypeError. Aggregate is the base of MinK/MaxK, the per-group 'keep k records' expressions, and its dict form is a single-entry mapping like {"$min_k": {"keys": [...], "k": n}} — mirroring what MinK.to_dict()/MaxK.to_dict() emit (operator.py:1440,1449). A list, string, or None cannot name an operator, so decoding aborts immediately. In normal use this is reached through GroupBy.from_dict, which validates that the group_by 'aggregate' field is a dict first (operator.py:1530-1533), so a direct Aggregate.from_dict call on bad input is the usual trigger.

Source

Thrown at clients/js/packages/chromadb-core/src/ChromaFetch.ts:109

        case 504:
          throw new ChromaConnectionError(
            `Unable to connect to the chromadb server. Please try again later.`,
          );
      }

      throw new Error(
        `Failed to fetch ${input} with status ${resp.status}: ${resp.statusText}`,
      );
    }

    if (respBody?.error) {
      throw parseServerError(respBody.error);
    }

    return resp;
  } catch (error) {
    if (isOfflineError(error)) {
      throw new ChromaConnectionError(
        "Failed to connect to chromadb. Make sure your server is running and try again. If you are running from a browser, make sure that your chromadb instance is configured to allow requests from the current origin using the CHROMA_SERVER_CORS_ALLOW_ORIGINS environment variable.",
        error,
      );
    }
    throw error;
  }
};

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Use the nested single-operator mapping: {"$min_k": {"keys": ["#score"], "k": 3}}.
  2. If you have a typed object already, pass it through — GroupBy accepts MinK/MaxK instances directly; from_dict is only for dicts.
  3. json.loads the payload string before decoding.
  4. Inside group_by, nest aggregate as a dict value: {"keys": [...], "aggregate": {"$min_k": {...}}}.

Example fix

// before
agg = Aggregate.from_dict(["$min_k", {"keys": ["#score"], "k": 3}])
# TypeError: Expected dict for Aggregate, got list

# after
agg = Aggregate.from_dict({"$min_k": {"keys": ["#score"], "k": 3}})
Defensive patterns

Strategy: type-guard

Validate before calling

def is_aggregate_payload(v: Any) -> bool:
    return isinstance(v, dict) and len(v) > 0

Type guard

def is_aggregate_dict(v: Any) -> TypeGuard[Dict[str, Any]]:
    return isinstance(v, dict) and len(v) == 1 and next(iter(v)) in {"$min_k", "$max_k"}

Try / catch

try:
    Aggregate.from_dict(payload)
except TypeError as e:
    raise ValueError(
        f"Aggregate must be a dict like {{'$min_k': {{'keys': [...], 'k': n}}}}, got {payload!r}"
    ) from e

Prevention

When it happens

Trigger: GroupBy.from_dict({"keys": [...], "aggregate": [...]}) is intercepted one step earlier by the aggregate-is-dict check; this specific error fires on direct calls like Aggregate.from_dict(["$min_k", {...}]) — a positional pair instead of a mapping; Aggregate.from_dict(MinK(...)) — passing the typed object itself; Aggregate.from_dict(None) or a JSON string body that was not json.loads-ed.

Common situations: Wrappers that accept 'aggregate' params of several shapes and forward them unconverted; double-encoded JSON payloads; refactoring from typed MinK(...) constructors to dict payloads and forwarding the old object; config systems delivering a list of operator/args pairs.

Related errors


AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16). Data as JSON: /api/errors/3a6f6e53e9c45b4c. Report an issue: GitHub.