chroma-core/chroma · error · Error

GroupBy keys cannot be empty

Error message

GroupBy keys cannot be empty

What it means

GroupBy requires at least one grouping key (the metadata field(s) to group records by, e.g. 'category'). The constructor rejects an empty keys array with a plain Error, because a group-by over no fields is meaningless and would silently produce a wrong query.

Source

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

      },
    };
  }
}

export interface GroupByJSON {
  keys: string[];
  aggregate: AggregateJSON;
}

export type GroupByInput = GroupBy | GroupByJSON;

export class GroupBy {
  constructor(
    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'");
      }

View on GitHub (pinned to aecdd12c8a)

Solutions

  1. Provide at least one metadata field to group by: GroupBy.from({ keys: ["category"], aggregate })
  2. Validate the facet/field selection is non-empty before building the GroupBy, and return a domain-level error to the caller
  3. Double-check you did not swap the outer group-by keys with the inner aggregate keys

Example fix

// before
const gb = GroupBy.from({
  keys: facets.filter((f) => f.enabled), // empty selection -> Error
  aggregate: Aggregate.minK(["score"], 5),
});

// after
const enabled = facets.filter((f) => f.enabled);
if (enabled.length === 0) throw new Error("Select at least one facet to group by");
const gb = GroupBy.from({ keys: enabled, aggregate: Aggregate.minK(["score"], 5) });
Defensive patterns

Strategy: validation

Validate before calling

const groupKeys = facets.filter((f) => f.enabled).map((f) => f.name);
if (groupKeys.length === 0) {
  throw new Error("Select at least one field to group by");
}
const gb = GroupBy.from({ keys: groupKeys, aggregate: Aggregate.minK(["score"], 5) });

Type guard

const hasGroupKeys = (keys: unknown): keys is string[] =>
  Array.isArray(keys) && keys.length > 0 && keys.every((k) => typeof k === "string");

Prevention

When it happens

Trigger: new GroupBy([], Aggregate.minK(["score"], 5)); or GroupBy.from({ keys: [], aggregate: { $min_k: { keys: ["score"], k: 5 } } }) — note Aggregate.from succeeds first, then the GroupBy constructor throws.

Common situations: Building the group-by key list dynamically from user-selected facets and receiving an empty selection. Copying the aggregate's keys into the group-by keys position (both are arrays named 'keys' in the JSON shape, an easy swap).

Related errors


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