@@ -5,6 +5,7 @@ import type {
55 Collection ,
66 CollectionConfiguration ,
77 CollectionMetadata ,
8+ Metadata ,
89 Where
910} from 'chromadb'
1011
@@ -145,7 +146,7 @@ export class Chroma extends VectorStore {
145146 const documentIds = options ?. ids ?? Array . from ( { length : vectors . length } , ( ) => uuid . v1 ( ) )
146147 const collection = await this . ensureCollection ( )
147148
148- const mappedMetadatas = documents . map ( ( { metadata } ) => {
149+ const mappedMetadatas : Metadata [ ] = documents . map ( ( { metadata } ) => {
149150 let locFrom
150151 let locTo
151152
@@ -162,7 +163,7 @@ export class Chroma extends VectorStore {
162163
163164 if ( newMetadata . loc ) delete newMetadata . loc
164165
165- return newMetadata
166+ return sanitizeMetadata ( newMetadata )
166167 } )
167168
168169 await collection . upsert ( {
@@ -343,3 +344,27 @@ function ensureCollectionName(collectionName?: string) {
343344 }
344345 return collectionName
345346}
347+
348+ /**
349+ * Sanitizes metadata to only include Chroma-compatible primitive values.
350+ * Chroma metadata only supports boolean, number, string, and null values.
351+ * Arrays and objects are JSON stringified to preserve the data.
352+ */
353+ function sanitizeMetadata ( metadata : Document [ 'metadata' ] ) : Metadata {
354+ const sanitized : Metadata = { }
355+ for ( const [ key , value ] of Object . entries ( metadata ) ) {
356+ if ( value === null || typeof value === 'boolean' || typeof value === 'number' || typeof value === 'string' ) {
357+ sanitized [ key ] = value
358+ } else if ( value !== undefined ) {
359+ try {
360+ const stringified = JSON . stringify ( value )
361+ if ( stringified !== undefined ) {
362+ sanitized [ key ] = stringified
363+ }
364+ } catch {
365+ // Skip values that cannot be stringified (e.g. circular references)
366+ }
367+ }
368+ }
369+ return sanitized
370+ }
0 commit comments