chroma-core/chroma · error · ChromaQuotaExceededError

${respBody?.message}

Error message

${respBody?.message}

What it means

_parse_k_aggregate() (operator.py:1366-1367) raises ValueError when the 'keys' list of a '$min_k'/'$max_k' aggregation is empty (or an empty tuple). An aggregation must rank group members on at least one field, so {"$min_k": {"keys": [], "k": 3}} names nothing to order by and is rejected before MinK/MaxK construction. Note the asymmetry with Select.from_dict, which happily accepts {"keys": []} (operator.py:1288) — empty is valid for selection but not for aggregation.

Source

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

        case 401:
          throw new ChromaUnauthorizedError(`Unauthorized`);
        case 403:
          throw new ChromaForbiddenError(
            `You do not have permission to access the requested resource.`,
          );
        case 404:
          throw new ChromaNotFoundError(
            `The requested resource could not be found: ${input}`,
          );
        case 409:
          throw new ChromaUniqueError("The resource already exists");
        case 422:
          if (
            respBody?.message &&
            (respBody?.message.startsWith("Quota exceeded") ||
              respBody?.message.startsWith("Billing limit exceeded"))
          ) {
            throw new ChromaQuotaExceededError(respBody?.message);
          }
          break;
        case 500:
          throw parseServerError(respBody?.error);
        case 502:
        case 503:
        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) {

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Provide at least one ranking key — almost always ["#score"] for similarity ranking.
  2. If keys are computed, validate non-emptiness at the source and raise a clear config error instead of sending an empty aggregate.
  3. Do not reuse Select examples here: empty keys are legal for Select and illegal for Aggregate.
  4. For pure per-group top-k by relevance, use {"keys": ["#score"], "k": n} with $min_k (lower Chroma score = better).

Example fix

// before
aggregate = {"$min_k": {"keys": [], "k": 3}}   # ValueError: $min_k keys cannot be empty

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

Strategy: validation

Validate before calling

def agg_keys_nonempty(payload: dict) -> bool:
    op = next(iter(payload))
    body = payload.get(op, {})
    return isinstance(body, dict) and isinstance(body.get("keys"), (list, tuple)) and len(body["keys"]) > 0

Type guard

def is_valid_aggregate_keys(v: Any) -> TypeGuard[Dict[str, Dict[str, Any]]]:
    if not (isinstance(v, dict) and len(v) == 1):
        return False
    body = next(iter(v.values()))
    return (
        isinstance(body, dict)
        and isinstance(body.get("keys"), (list, tuple))
        and len(body["keys"]) > 0
        and all(isinstance(k, str) for k in body["keys"])
    )

Try / catch

try:
    Aggregate.from_dict(agg)
except ValueError as e:
    if "keys cannot be empty" in str(e):
        raise ValueError("Aggregation needs at least one ranking key, "
                         "usually ['#score']") from e
    raise

Prevention

When it happens

Trigger: {"$min_k": {"keys": [], "k": 3}} explicitly; a dynamic key list that evaluated to empty (group-by field name variable was blank); YAML where the keys array's entries were all commented out; JSON merge that produced {"keys": []} after filtering out invalid entries.

Common situations: Config templating that computes keys from user input and emits [] when nothing matches; optional-key logic that defaults to an empty list instead of failing earlier; test fixtures copied from a Select example (where [] is legal) into an aggregate; pipeline stages that filter keys and can silently empty them.

Related errors


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