{"record":{"id":"bc3d0992160dbdea","repo":"chroma-core/chroma","slug":"expected-ids-to-be-strings-found-typeof-ids-i","errorCode":null,"errorMessage":"Expected ids to be strings, found ${typeof ids[i]} at index ${i}","messagePattern":"Expected ids to be strings, found (.+?) at index (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"clients/js/packages/chromadb-core/src/utils.ts","lineNumber":132,"sourceCode":"  const { ids, embeddings, metadatas, documents } = arrayifyParams(reqParams);\n\n  if (!embeddings && !documents && !update) {\n    throw new Error(\"embeddings and documents cannot both be undefined\");\n  }\n\n  const embeddingsArray = embeddings\n    ? embeddings\n    : documents\n    ? await embeddingFunction.generate(documents)\n    : undefined;\n\n  if (!embeddingsArray && !update) {\n    throw new Error(\"Failed to generate embeddings for your request.\");\n  }\n\n  for (let i = 0; i < ids.length; i += 1) {\n    if (typeof ids[i] !== \"string\") {\n      throw new Error(\n        `Expected ids to be strings, found ${typeof ids[i]} at index ${i}`,\n      );\n    }\n  }\n\n  if (\n    (embeddingsArray !== undefined && ids.length !== embeddingsArray.length) ||\n    (metadatas !== undefined && ids.length !== metadatas.length) ||\n    (documents !== undefined && ids.length !== documents.length)\n  ) {\n    throw new Error(\n      \"ids, embeddings, metadatas, and documents must all be the same length\",\n    );\n  }\n\n  const uniqueIds = new Set(ids);\n  if (uniqueIds.size !== ids.length) {\n    const duplicateIds = ids.filter(","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/clients/js/packages/chromadb-core/src/utils.ts#L114-L150","documentation":"prepareRecordRequest() iterates ids and requires every element to be a JavaScript string; the first offender is reported with its typeof ('number', 'object', 'boolean', ...). Chroma record ids are strings on the wire (UUIDs or custom string ids), and silently coercing would risk silent data mismatches, so the client fails fast before sending anything.","triggerScenarios":"collection.add({ ids: [1, 2, 3], ... }) with numeric primary keys from a SQL table; ids containing null/undefined from a sparse array; Mongo ObjectId objects; ids: [crypto.randomUUID()] fine, but ids from JSON parsed with numbers kept as numbers.","commonSituations":"Bulk-importing rows whose primary keys are integers; mapping ORM rows and forgetting to stringify; passing BigInt ids (typeof 'bigint'); arrays built with a stray undefined hole.","solutions":["Stringify ids at the boundary: ids: rows.map((r) => String(r.id)).","For UUID columns keep them strings; for numbers decide on a canonical format (e.g., String(n)) and use it consistently for add/get/update/delete.","Log typeof of the reported index if unsure which record is malformed."],"exampleFix":"// before\nawait collection.add({\n  ids: [1, 2, 3], // typeof 'number' at index 0 -> throws\n  documents: [\"a\", \"b\", \"c\"],\n});\n\n// after\nawait collection.add({\n  ids: [\"1\", \"2\", \"3\"], // rows.map(r => String(r.id))\n  documents: [\"a\", \"b\", \"c\"],\n});","handlingStrategy":"type-guard","validationCode":"// Coerce at the boundary — decide the canonical id format once\nconst ids = rows.map((r) => String(r.id));","typeGuard":"const isStringIdArray = (ids: unknown[]): ids is string[] =>\n  ids.every((id) => typeof id === \"string\");\n\nif (!isStringIdArray(ids)) {\n  const i = ids.findIndex((id) => typeof id !== \"string\");\n  throw new Error(`ids[${i}] is ${typeof ids[i]} — stringify ids before add()`);\n}","tryCatchPattern":null,"preventionTips":["Map external primary keys to strings exactly once, at ingestion time, and use that form for add/get/update/delete alike.","Enable strict TypeScript checks (no implicit any) so numeric id arrays from untyped sources get caught earlier."],"tags":["records","ids","type-error","validation","add"],"backgroundTag":"invalid-record-id-type","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}