{"record":{"id":"81c95deb5d15f9cd","repo":"chroma-core/chroma","slug":"mink-k-must-be-positive","errorCode":null,"errorMessage":"MinK k must be positive","messagePattern":"MinK k must be positive","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"clients/new-js/packages/chromadb/src/execution/expression/groupBy.ts","lineNumber":68,"sourceCode":"    );\n  }\n\n  public static maxK(keys: (Key | string)[], k: number): MaxK {\n    return new MaxK(\n      keys.map((key) => (key instanceof Key ? key : new Key(key))),\n      k,\n    );\n  }\n}\n\nexport class MinK extends Aggregate {\n  constructor(public readonly keys: Key[], public readonly k: number) {\n    super();\n    if (keys.length === 0) {\n      throw new Error(\"MinK keys cannot be empty\");\n    }\n    if (k <= 0) {\n      throw new Error(\"MinK k must be positive\");\n    }\n  }\n\n  public toJSON(): AggregateJSON {\n    return {\n      $min_k: {\n        keys: this.keys.map((key) => key.name),\n        k: this.k,\n      },\n    };\n  }\n}\n\nexport class MaxK extends Aggregate {\n  constructor(public readonly keys: Key[], public readonly k: number) {\n    super();\n    if (keys.length === 0) {\n      throw new Error(\"MaxK keys cannot be empty\");","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/clients/new-js/packages/chromadb/src/execution/expression/groupBy.ts#L50-L86","documentation":"MinK's constructor requires k (the number of smallest values to return) to be a positive integer. k <= 0 — including 0 — is rejected with a plain Error at construction time, because 'return the smallest 0 values' is almost always a misconfiguration rather than an intent.","triggerScenarios":"new MinK([K.SCORE], 0); Aggregate.minK([\"score\"], -1); or aggregate JSON { $min_k: { keys: [\"score\"], k: 0 } } parsed by Aggregate.from.","commonSituations":"k read from an environment variable or config file that defaults to 0 when unset (parseInt(undefined) → NaN also fails the <= 0 check after NaN comparisons; explicit 0 is the classic case). App semantics where 0 means 'no limit' — here it must be a positive count instead.","solutions":["Pass a positive integer for k (k >= 1)","If k comes from config, coerce and clamp: Math.max(1, Number(process.env.TOP_K) || 5)","Treat 'unset' as a sensible default (e.g. 5) rather than 0"],"exampleFix":"// before\nconst agg = Aggregate.minK([\"score\"], Number(cfg.topK)); // cfg.topK = 0 -> Error\n\n// after\nconst topK = Math.max(1, Number(cfg.topK) || 5);\nconst agg = Aggregate.minK([\"score\"], topK);","handlingStrategy":"validation","validationCode":"const k = Number(cfg.topK);\nif (!Number.isInteger(k) || k <= 0) {\n  throw new Error(`topK must be a positive integer, got ${cfg.topK}`);\n}\nconst agg = Aggregate.minK([\"score\"], k);","typeGuard":"const isPositiveInt = (v: unknown): v is number =>\n  typeof v === \"number\" && Number.isInteger(v) && v > 0;","tryCatchPattern":null,"preventionTips":["Clamp config-sourced k: Math.max(1, Number(x) || 5)","Never use 0 to mean 'no limit' — k is an explicit count","Validate query params at the API boundary before they reach query construction"],"tags":["chroma","group-by","mink","numeric"],"backgroundTag":"invalid-numeric-argument","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}