chroma-core/chroma · error · ChromaClientError
Bad request to ${input} with status: ${resp.statusText}
Error message
Bad request to ${input} with status: ${resp.statusText} What it means
Select.from_dict() (operator.py:1315-1319) allows exactly one top-level key, 'keys', in a Select dict; any extra field raises ValueError with the offending key names. The dict form is intentionally minimal ({"keys": [...]}) because it mirrors what Select.to_dict() emits (operator.py:1275), so extra entries indicate the caller mixed fields from another part of the Search payload (filter, rank, limit, group_by) into the select object. This strictness catches payload-shape confusion early rather than silently ignoring typos.
Source
Thrown at clients/js/packages/chromadb-core/src/ChromaFetch.ts:63
* It is intended to be passed to the ApiApi constructor.
*/
export const chromaFetch: FetchAPI = async (
input: RequestInfo | URL,
init?: RequestInit,
): Promise<Response> => {
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") ||View on GitHub (pinned to aecdd12c8a)
Solutions
- Strip the select object down to {"keys": [...]} — that is the only accepted shape.
- Move misplaced fields to the right level: limit belongs on Search(limit=10) or the limit dict, aggregate belongs inside group_by, not select.
- If a wrapper decorates payloads with bookkeeping keys, strip them before decode: payload = {k: v for k, v in payload.items() if k == 'keys'} — but prefer fixing the wrapper so only schema fields travel.
- Validate payloads against Select.to_dict()'s output shape before sending: the key set must equal {'keys'}.
Example fix
// before
select = {"keys": ["#document"], "limit": 10, "offset": 0}
# ValueError: Unexpected keys in Select dict: {'limit', 'offset'}
# after
search = Search(select={"keys": ["#document"]}, limit=10) Defensive patterns
Strategy: validation
Validate before calling
def select_payload_shape_ok(payload: dict) -> bool:
return set(payload.keys()) <= {"keys"} Type guard
def is_select_shaped(v: Any) -> TypeGuard[Dict[str, Any]]:
return isinstance(v, dict) and set(v.keys()) <= {"keys"} Try / catch
try:
Select.from_dict(payload)
except ValueError as e:
if "Unexpected keys" in str(e):
payload = {k: v for k, v in payload.items() if k == "keys"}
Select.from_dict(payload)
else:
raise Prevention
- Keep Search-level fields (limit, where, rank) at the Search level, never inside select.
- Validate generated payloads against set(payload) == {'keys'} before send.
- Do not let wrappers inject version/comment keys into payload sub-objects.
When it happens
Trigger: Search(select={"keys": ["#document"], "limit": 10}) — a Search-level field nested inside select; {"keys": [...], "k": 3} — an Aggregate-style field leaking into Select; {"keys": [...], "document": True} from attempting per-key flags; copy-pasting a GroupBy dict ({"keys": ..., "aggregate": ...}) as the select argument, which also trips this after the keys pass.
Common situations: Flattening a Search.to_dict() blob and feeding a sub-object that still carries sibling fields; hand-authoring request payloads where nested-field boundaries are guessed; merging config snippets that each add a field to the same dict; wrappers that inject metadata (e.g. a version or comment key) into every payload sub-object.
Related errors
- You must provide either queryEmbeddings or queryTexts
- Unexpected keys in Limit dict: {unexpected_keys}
- Multiple embedding functions provided. Please provide only o
- You do not have permission to access the requested resource.
- The requested resource could not be found: ${input}
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/bc5416a2b15d2a08.
Report an issue: GitHub.