{"record":{"id":"28871e2382fde618","repo":"chroma-core/chroma","slug":"respbody-message","errorCode":null,"errorMessage":"${respBody?.message}","messagePattern":"\\$\\{respBody\\?\\.message\\}","errorType":"http","errorClass":"ChromaQuotaExceededError","httpStatus":422,"severity":"error","filePath":"clients/js/packages/chromadb-core/src/ChromaFetch.ts","lineNumber":84,"sourceCode":"        case 401:\n          throw new ChromaUnauthorizedError(`Unauthorized`);\n        case 403:\n          throw new ChromaForbiddenError(\n            `You do not have permission to access the requested resource.`,\n          );\n        case 404:\n          throw new ChromaNotFoundError(\n            `The requested resource could not be found: ${input}`,\n          );\n        case 409:\n          throw new ChromaUniqueError(\"The resource already exists\");\n        case 422:\n          if (\n            respBody?.message &&\n            (respBody?.message.startsWith(\"Quota exceeded\") ||\n              respBody?.message.startsWith(\"Billing limit exceeded\"))\n          ) {\n            throw new ChromaQuotaExceededError(respBody?.message);\n          }\n          break;\n        case 500:\n          throw parseServerError(respBody?.error);\n        case 502:\n        case 503:\n        case 504:\n          throw new ChromaConnectionError(\n            `Unable to connect to the chromadb server. Please try again later.`,\n          );\n      }\n\n      throw new Error(\n        `Failed to fetch ${input} with status ${resp.status}: ${resp.statusText}`,\n      );\n    }\n\n    if (respBody?.error) {","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/clients/js/packages/chromadb-core/src/ChromaFetch.ts#L66-L102","documentation":"_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.","triggerScenarios":"{\"$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.","commonSituations":"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.","solutions":["Provide at least one ranking key — almost always [\"#score\"] for similarity ranking.","If keys are computed, validate non-emptiness at the source and raise a clear config error instead of sending an empty aggregate.","Do not reuse Select examples here: empty keys are legal for Select and illegal for Aggregate.","For pure per-group top-k by relevance, use {\"keys\": [\"#score\"], \"k\": n} with $min_k (lower Chroma score = better)."],"exampleFix":"// before\naggregate = {\"$min_k\": {\"keys\": [], \"k\": 3}}   # ValueError: $min_k keys cannot be empty\n\n# after\naggregate = {\"$min_k\": {\"keys\": [\"#score\"], \"k\": 3}}","handlingStrategy":"validation","validationCode":"def agg_keys_nonempty(payload: dict) -> bool:\n    op = next(iter(payload))\n    body = payload.get(op, {})\n    return isinstance(body, dict) and isinstance(body.get(\"keys\"), (list, tuple)) and len(body[\"keys\"]) > 0","typeGuard":"def is_valid_aggregate_keys(v: Any) -> TypeGuard[Dict[str, Dict[str, Any]]]:\n    if not (isinstance(v, dict) and len(v) == 1):\n        return False\n    body = next(iter(v.values()))\n    return (\n        isinstance(body, dict)\n        and isinstance(body.get(\"keys\"), (list, tuple))\n        and len(body[\"keys\"]) > 0\n        and all(isinstance(k, str) for k in body[\"keys\"])\n    )","tryCatchPattern":"try:\n    Aggregate.from_dict(agg)\nexcept ValueError as e:\n    if \"keys cannot be empty\" in str(e):\n        raise ValueError(\"Aggregation needs at least one ranking key, \"\n                         \"usually ['#score']\") from e\n    raise","preventionTips":["Default computed key lists to ['#score'] instead of [].","Fail config loading when a computed keys list is empty rather than emitting [].","Do not port Select examples (where keys: [] is legal) into aggregates."],"tags":["chromadb","aggregate","empty-list","valueerror","min-k","max-k"],"backgroundTag":"empty-required-field","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}