chroma-core/chroma · error · ChromaForbiddenError

You do not have permission to access the requested resource.

Error message

You do not have permission to access the requested resource.

What it means

_parse_k_aggregate() (operator.py:1358-1359) raises ValueError when the inner dict of a '$min_k'/'$max_k' aggregation has no 'keys' field. 'keys' tells the aggregation which record fields to rank within each group — typically ["#score"] or a metadata field like ["priority", "#score"] for tiebreaking — so an aggregation without it is unexecutable and is rejected before MinK/MaxK are constructed (operator.py:1422-1427). The required inner shape is exactly {"keys": [...], "k": n}.

Source

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

  try {
    const resp = await fetch(input, init);

    const clonedResp = resp.clone();
    const respBody = await clonedResp.json();
    if (!clonedResp.ok) {
      const error = createErrorByType(respBody?.error, respBody?.message);
      if (error) {
        throw error;
      }
      switch (resp.status) {
        case 400:
          throw new ChromaClientError(
            `Bad request to ${input} with status: ${resp.statusText}`,
          );
        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:

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Add the required field: {"$min_k": {"keys": ["#score"], "k": 3}} — most often keys is ["#score"].
  2. Spell the field exactly 'keys'; synonyms like 'key', 'fields', 'on' are not accepted.
  3. For multi-criteria ranking pass multiple entries in order: {"keys": ["priority", "#score"], "k": 5}.
  4. If generating payloads from code, build them from a typed MinK(...).to_dict() so field names can never drift.

Example fix

// before
aggregate = {"$min_k": {"k": 3}}        # ValueError: $min_k requires 'keys' field

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

Strategy: validation

Validate before calling

def agg_has_keys_field(payload: dict) -> bool:
    op = next(iter(payload))
    body = payload.get(op, {})
    return isinstance(body, dict) and "keys" in body

Type guard

def is_complete_k_aggregate(v: Any) -> TypeGuard[Dict[str, Dict[str, Any]]]:
    if not (isinstance(v, dict) and len(v) == 1):
        return False
    op, body = next(iter(v.items()))
    return (
        op in {"$min_k", "$max_k"}
        and isinstance(body, dict)
        and "keys" in body
        and "k" in body
    )

Try / catch

try:
    Aggregate.from_dict(agg)
except ValueError as e:
    if "requires 'keys' field" in str(e):
        op = next(iter(agg))
        agg[op]["keys"] = ["#score"]  # or fail loudly with a config error
    else:
        raise

Prevention

When it happens

Trigger: {"$min_k": {"k": 3}} — only k supplied; field renamed in config ('key', 'fields', 'by') instead of the required 'keys'); JSON payload built programmatically that skips keys when a default was intended; partial merge of config templates that dropped the keys entry.

Common situations: Config authors assuming keys defaults to '#score'; renaming payload fields for house style without updating the consumer; YAML stripped of the keys line by a bad edit or templating conditional; versions of a wrapper that emit only k and rely on server defaults that Chroma does not have.

Related errors


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