chroma-core/chroma · error · TypeError

GroupBy requires 'keys' array

Error message

GroupBy requires 'keys' array

What it means

When GroupBy.from() receives a plain object (the serialized GroupByJSON shape), it requires a 'keys' property that is an Array. A missing keys field, or keys set to a string/number/null instead of an array, raises this TypeError before construction.

Source

Thrown at clients/new-js/packages/chromadb/src/execution/expression/groupBy.ts:130

    public readonly keys: Key[],
    public readonly aggregate: Aggregate,
  ) {
    if (keys.length === 0) {
      throw new Error("GroupBy keys cannot be empty");
    }
  }

  public static from(input: GroupByInput | undefined): GroupBy | undefined {
    if (input === undefined || input === null) {
      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

  1. Include keys as an array of field names: { keys: ["category"], aggregate }
  2. Wrap single field names in brackets: keys: ["category"], not keys: "category"
  3. Prefer constructing GroupBy directly with Key instances instead of raw JSON

Example fix

// before
GroupBy.from({ keys: "category", aggregate: Aggregate.minK(["score"], 5) }); // TypeError

// after
GroupBy.from({ keys: ["category"], aggregate: Aggregate.minK(["score"], 5) });
Defensive patterns

Strategy: type-guard

Validate before calling

if (!Array.isArray(queryJson.keys) || queryJson.keys.length === 0) {
  throw new Error("GroupBy JSON requires keys: string[] (wrap single names in an array)");
}
const gb = GroupBy.from(queryJson);

Type guard

function isGroupByJSON(v: unknown): v is { keys: string[]; aggregate: unknown } {
  return (
    typeof v === "object" &&
    v !== null &&
    Array.isArray((v as { keys?: unknown }).keys) &&
    "aggregate" in v
  );
}

Try / catch

try {
  const gb = GroupBy.from(payload);
} catch (e) {
  if (e instanceof TypeError && /requires 'keys'/.test(e.message)) {
    // fix payload: keys must be an array like ["category"]
  } else throw e;
}

Prevention

When it happens

Trigger: GroupBy.from({ aggregate: { $min_k: { keys: ["score"], k: 5 } } }) — keys omitted. GroupBy.from({ keys: "category", aggregate }) — keys is a string, not an array.

Common situations: Hand-writing the group-by JSON and abbreviating keys. Partial JSON produced by destructuring or object spread that drops the keys field. Treating a single field name as acceptable (must be wrapped in an array).

Related errors


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