chroma-core/chroma · error · TypeError

GroupBy requires 'aggregate'

Error message

GroupBy requires 'aggregate'

What it means

When GroupBy.from() receives a plain object, it requires a truthy 'aggregate' property alongside keys. Omitting aggregate — or setting it to null/0/empty — raises this TypeError, because a group-by without an aggregation has nothing to compute per group.

Source

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

    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. Always pair keys with an aggregate: GroupBy.from({ keys: ["category"], aggregate: Aggregate.minK(["score"], 5) })
  2. If the aggregate is conditionally built, default it (e.g. minK over 'score' with k=5)
  3. Use the typed Aggregate helpers so the aggregate is never a falsy half-constructed value

Example fix

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

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

Strategy: validation

Validate before calling

const aggregate = buildAggregate(opts) ?? Aggregate.minK(["score"], 5);
const gb = GroupBy.from({ keys: ["category"], aggregate });

Type guard

const hasAggregate = (v: unknown): v is { aggregate: unknown } =>
  typeof v === "object" && v !== null && "aggregate" in v && (v as { aggregate: unknown }).aggregate != null;

Prevention

When it happens

Trigger: GroupBy.from({ keys: ["category"] }) — aggregate omitted entirely. GroupBy.from({ keys: ["category"], aggregate: null }) — null is falsy and rejected.

Common situations: Building the group-by JSON incrementally and forgetting to attach the aggregate. Conditional code that only sets aggregate when a option flag is on, leaving it undefined otherwise. Confusing the group-by keys requirement with the aggregate requirement after refactoring.

Related errors


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