{"record":{"id":"8ec8e02d6e27fda6","repo":"chroma-core/chroma","slug":"expected-metadata-to-be-non-empty","errorCode":null,"errorMessage":"Expected metadata to be non-empty","messagePattern":"Expected metadata to be non-empty","errorType":"validation","errorClass":"ChromaValueError","httpStatus":null,"severity":"error","filePath":"clients/new-js/packages/chromadb/src/utils.ts","lineNumber":260,"sourceCode":"\n  return (\n    indices.every((e) => typeof e === \"number\") &&\n    values.every((e) => typeof e === \"number\")\n  );\n};\n\n/**\n * Validates metadata object for correct types and non-emptiness.\n * @param metadata - Metadata object to validate\n * @throws ChromaValueError if metadata is invalid\n */\nexport const validateMetadata = (metadata?: Metadata) => {\n  if (!metadata) {\n    return;\n  }\n\n  if (Object.keys(metadata).length === 0) {\n    throw new ChromaValueError(\"Expected metadata to be non-empty\");\n  }\n\n  const validateMetadataListValue = (key: string, v: unknown[]): void => {\n    if (v.length === 0) {\n      throw new ChromaValueError(\n        `Expected metadata list value for key '${key}' to be non-empty`,\n      );\n    }\n    const firstType = typeof v[0];\n    for (const item of v) {\n      if (\n        typeof item !== \"string\" &&\n        typeof item !== \"number\" &&\n        typeof item !== \"boolean\"\n      ) {\n        throw new ChromaValueError(\n          `Expected metadata list value for key '${key}' to contain only strings, numbers, or booleans, got ${typeof item}`,\n        );","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/chroma-core/chroma/blob/aecdd12c8a891610db8653630b066b32ceb678b5/clients/new-js/packages/chromadb/src/utils.ts#L242-L278","documentation":"Thrown by validateMetadata in the Chroma JavaScript client when a metadata object is supplied but contains zero keys. Validation is skipped for undefined/null metadata, but an empty object {} is treated as malformed input and raises ChromaValueError before any network call. Express 'no metadata' as null (or omit the entry), never as {}.","triggerScenarios":"Calling collection.add() or upsert() with metadatas: [{}] (an empty object in the array). Building metadata by spreading optional fields that are all absent, e.g. {...(filters ?? {})} yielding {}. Mapping over a data source where some rows produce no metadata keys.","commonSituations":"Dynamic metadata built from optional user input or form fields; JSON deserialization that yields empty objects; refactoring that replaced null with {} during a TypeScript strictness cleanup.","solutions":["Pass null (or omit the entry) instead of {} for records with no metadata: metadatas: [null].","Make sure every metadata object you pass has at least one string/number/boolean key.","Sanitize before the call: metadatas.map(m => m && Object.keys(m).length ? m : null)."],"exampleFix":"// before\nawait collection.add({ ids: ['1'], documents: ['doc'], metadatas: [{}] });\n\n// after\nawait collection.add({ ids: ['1'], documents: ['doc'], metadatas: [null] });","handlingStrategy":"validation","validationCode":"const safeMetadatas = metadatas.map(m => (m && Object.keys(m).length === 0 ? null : m));\nawait collection.add({ ids, documents, metadatas: safeMetadatas });","typeGuard":"const isNonEmptyMetadata = (m: unknown): m is Record<string, unknown> =>\n  typeof m === 'object' && m !== null && Object.keys(m).length > 0;","tryCatchPattern":"try {\n  await collection.add({ ids, metadatas });\n} catch (e) {\n  if ((e as Error).message.includes('metadata to be non-empty')) {\n    const fixed = metadatas.map(m => (m && Object.keys(m).length ? m : null));\n    await collection.add({ ids, metadatas: fixed }); // retry with normalized metadata\n  } else {\n    throw e;\n  }\n}","preventionTips":["Never use {} to mean 'no metadata' — use null or omit the entry.","Centralize metadata construction in one builder that returns null for empty objects.","Add a unit test over your metadata builder asserting no empty objects reach add()/upsert()."],"tags":["metadata","validation","javascript","chroma"],"backgroundTag":"invalid-metadata","analyzedSha":"aecdd12c8a891610db8653630b066b32ceb678b5","analyzedAt":"2026-08-16T21:53:27.228Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}