{"record":{"id":"a2020bc3edb6531e","repo":"chroma-core/chroma","slug":"select-keys-must-be-strings-or-key-instances","errorCode":null,"errorMessage":"Select keys must be strings or Key instances","messagePattern":"Select keys must be strings or Key instances","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"clients/new-js/packages/chromadb/src/execution/expression/select.ts","lineNumber":20,"sourceCode":"\nexport type SelectKeyInput = string | Key;\n\nexport type SelectInput =\n  | Select\n  | Iterable<SelectKeyInput>\n  | { keys?: Iterable<SelectKeyInput> }\n  | null\n  | undefined;\n\nexport class Select {\n  private readonly keys: string[];\n\n  constructor(keys: Iterable<SelectKeyInput> = []) {\n    const unique = new Set<string>();\n    for (const key of keys) {\n      const normalized = key instanceof Key ? key.name : key;\n      if (typeof normalized !== \"string\") {\n        throw new TypeError(\"Select keys must be strings or Key instances\");\n      }\n      unique.add(normalized);\n    }\n    this.keys = Array.from(unique);\n  }\n\n  public static from(input: SelectInput): Select {\n    if (input instanceof Select) {\n      return new Select(input.keys);\n    }\n\n    if (input === null || input === undefined) {\n      return new Select();\n    }\n\n    if (Symbol.iterator in Object(input)) {\n      return new Select(input as Iterable<SelectKeyInput>);\n    }","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/clients/new-js/packages/chromadb/src/execution/expression/select.ts#L2-L38","documentation":"Thrown by the Select constructor in the Chroma JS client (select.ts:20) when an entry in the keys iterable is neither a string nor a Key instance. Key instances are unwrapped to their .name; anything else — numbers, null, objects, arrays — throws. Keys are also deduplicated into a Set, so only the type of each entry matters.","triggerScenarios":"new Select(['document', 42]); Select.from([null]); Select.from([{ name: 'doc' }]) — passing key-like plain objects instead of Key instances or strings; select: [1, 2] from code that used numeric column indices from another API.","commonSituations":"Migrating from an ORM or SQL mindset where columns are referenced by index; JSON configs listing select fields where a value is null or numeric; mixed arrays produced by mapping over heterogeneous data; key objects imported from a different copy of the chromadb package (instanceof fails across duplicated classes), which then need .name passed explicitly.","solutions":["Use plain strings: new Select(['#document', 'metadata_field'])","Use the K factory or Key constants: Select.from([Key.DOCUMENT, K('tags')])","Sanitize dynamic lists first: keys.filter(k => typeof k === 'string' || k instanceof Key)"],"exampleFix":"// before\nconst select = Select.from(['document', meta.fieldId, null]); // non-strings throw\n\n// after\nconst select = Select.from(\n  ['document', meta.fieldId, null].filter(\n    (k): k is string => typeof k === 'string',\n  ),\n);","handlingStrategy":"type-guard","validationCode":"const isSelectKey = (v: unknown): v is string =>\n  typeof v === 'string';\nconst safeKeys = rawKeys\n  .map(k => (k instanceof Key ? k.name : k))\n  .filter(isSelectKey);\nconst select = Select.from(safeKeys);","typeGuard":"const isSelectKeyInput = (v: unknown): v is string | Key =>\n  typeof v === 'string' || v instanceof Key;","tryCatchPattern":"try {\n  const select = Select.from(keys);\n} catch (e) {\n  if (e instanceof TypeError && e.message.includes('Select keys')) {\n    return Select.from(keys.filter(isSelectKeyInput));\n  }\n  throw e;\n}","preventionTips":["Express select fields as strings or K('field')/Key constants","Map Key-like objects to their .name string when data crosses package boundaries","Filter untrusted key lists (nulls from JSON) before Select.from"],"tags":["select","keys","input-validation","type-error","client-side"],"backgroundTag":"invalid-argument-type","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}