chroma-core/chroma · error · Error

No API key provided

Error message

No API key provided

What it means

Aggregate.from_dict() (operator.py:1412-1413) raises ValueError when given an empty dict {}. An Aggregate dict must name exactly one operator ('$min_k' or '$max_k') whose value carries the keys/k parameters; an empty mapping names none, so there is nothing to construct and the decoder refuses it. This differs deliberately from GroupBy.from_dict, where {} is legal and means 'no grouping' (operator.py:1514-1515) — empty is meaningful for GroupBy but meaningless for Aggregate.

Source

Thrown at clients/js/packages/chromadb-core/src/CloudClient.ts:28

  tenant?: string;
  cloudHost?: string;
  cloudPort?: string;
}

class CloudClient extends ChromaClient {
  constructor({
    apiKey,
    database,
    tenant,
    cloudHost,
    cloudPort,
  }: CloudClientParams) {
    // If no API key is provided, try to load it from the environment variable
    if (!apiKey) {
      apiKey = process.env.CHROMA_API_KEY;
    }
    if (!apiKey) {
      throw new Error("No API key provided");
    }

    cloudHost = cloudHost || "https://api.trychroma.com";
    cloudPort = cloudPort || "8000";

    const path = `${cloudHost}:${cloudPort}`;

    const auth: AuthOptions = {
      provider: "token",
      credentials: apiKey,
      tokenHeaderType: "X_CHROMA_TOKEN",
    };

    return new ChromaClient({
      path: path,
      auth: auth,
      database,
      tenant,

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Fill in a real aggregation: {"aggregate": {"$min_k": {"keys": ["#score"], "k": 3}}} (top-3 per group by relevance).
  2. If you intended no grouping at all, use group_by={} (or omit it) — not an empty aggregate.
  3. Make your config layer reject or default an empty aggregate section instead of forwarding {}.
  4. Remember the two legal aggregate operators are exactly '$min_k' and '$max_k' (operator.py:1422-1429).

Example fix

// before
group_by = {"keys": ["category"], "aggregate": {}}
# ValueError: Aggregate dict cannot be empty (via GroupBy.from_dict)

# after
group_by = {"keys": ["category"], "aggregate": {"$min_k": {"keys": ["#score"], "k": 3}}}
Defensive patterns

Strategy: validation

Validate before calling

def aggregate_not_empty(payload: dict) -> bool:
    return isinstance(payload, dict) and len(payload) > 0

Type guard

def is_nonempty_aggregate(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(agg)
except ValueError as e:
    if "cannot be empty" in str(e):
        # decide intent: no grouping, or a missing aggregation spec
        raise ValueError("group_by aggregate cannot be {}; omit group_by for "
                         "no grouping, or supply {'$min_k': {...}}") from e
    raise

Prevention

When it happens

Trigger: GroupBy.from_dict({"keys": ["category"], "aggregate": {}}) — an explicitly empty aggregate alongside real keys; Aggregate.from_dict({}) direct calls; config templating that emits aggregate: {} when the user left the aggregation section blank; merging configs where all aggregate entries were filtered out.

Common situations: Config schemas that require an aggregate key but let it be empty; builders that initialize aggregate = {} and forget to fill it; authors copying the GroupBy empty-dict idiom into aggregate; JSON merge tools that strip unknown operators and leave {} behind.

Related errors


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