chroma-core/chroma · error · TypeError
GroupBy input must be a GroupBy instance or plain object
Error message
GroupBy input must be a GroupBy instance or plain object
What it means
GroupBy.from() accepts only a GroupBy instance, null/undefined (returns undefined), or a plain object (GroupByJSON). Any other input type — a string, number, boolean, array, or a class instance of another kind — falls through all branches and raises this TypeError.
Source
Thrown at clients/new-js/packages/chromadb/src/execution/expression/groupBy.ts:140
return undefined;
}
if (input instanceof GroupBy) {
return input;
}
if (isPlainObject(input)) {
const data = input as GroupByJSON;
if (!data.keys || !Array.isArray(data.keys)) {
throw new TypeError("GroupBy requires 'keys' array");
}
if (!data.aggregate) {
throw new TypeError("GroupBy requires 'aggregate'");
}
return new GroupBy(
data.keys.map((k) => new Key(k)),
Aggregate.from(data.aggregate),
);
}
throw new TypeError(
"GroupBy input must be a GroupBy instance or plain object",
);
}
public toJSON(): GroupByJSON {
return {
keys: this.keys.map((key) => key.name),
aggregate: this.aggregate.toJSON(),
};
}
}
View on GitHub (pinned to aecdd12c8a)
Solutions
- Parse JSON payloads first: GroupBy.from(JSON.parse(raw))
- Wrap arrays in the full shape: { keys: [...], aggregate: ... }
- After IPC/serialization boundaries, rely on the plain-object JSON shape rather than expecting instanceof GroupBy to hold
Example fix
// before
const gb = GroupBy.from(await cache.get("groupBy")); // stored JSON string -> TypeError
// after
const raw = await cache.get("groupBy");
const gb = GroupBy.from(typeof raw === "string" ? JSON.parse(raw) : raw); Defensive patterns
Strategy: type-guard
Validate before calling
const parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
throw new Error("GroupBy input must be a plain object { keys, aggregate }");
}
const gb = GroupBy.from(parsed); Type guard
import { isPlainObject } from "./helpers";
const isGroupByInput = (v: unknown): v is Record<string, unknown> =>
isPlainObject(v) && Array.isArray((v as { keys?: unknown }).keys) && "aggregate" in v; Try / catch
try {
const gb = GroupBy.from(cached);
} catch (e) {
if (e instanceof TypeError && /GroupBy input/.test(e.message)) {
// cached value is corrupt/strings — rebuild from defaults
} else throw e;
} Prevention
- JSON.parse stored payloads before GroupBy.from
- After IPC/serialization boundaries, pass the plain-object JSON shape, not class instances
- Wrap deserialization in one shared helper that also validates shape
When it happens
Trigger: GroupBy.from("category"); GroupBy.from(["category"]); or passing a JSON string like GroupBy.from(JSON.stringify(gb)) that was never parsed. Also passing a custom class instance that isn't GroupBy.
Common situations: Forgetting JSON.parse on a group-by payload read from a queue, cache, or database column. Passing an array of keys directly because the keys field is itself an array. Cross-boundary deserialization where class identity (instanceof GroupBy) is lost after structured clone or IPC.
Related errors
- Aggregate input must be an Aggregate instance or object with
- MinK keys cannot be empty
- MinK k must be positive
- MaxK keys cannot be empty
- MaxK k must be positive
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/81eedd5c4160c5d3.
Report an issue: GitHub.