FlowiseAI/Flowise · error · Error

Failed to hash metadata: ${e}. Please use a dict that can be

Error message

Failed to hash metadata: ${e}. Please use a dict that can be serialized using json.

What it means

Thrown by _HashedDocument.calculateHashes() when the internal _hashNestedDictToUUID() call fails during metadata hashing. _hashNestedDictToUUID uses JSON.stringify with a custom replacer (Object.keys(data).sort()) to serialize metadata before hashing; if the metadata contains values that JSON cannot represent (functions, symbols, circular references, BigInt), serialization throws and the catch at line 94 wraps it.

Source

Thrown at packages/components/src/indexing.ts:95

    calculateHashes(): void {
        const forbiddenKeys = ['hash_', 'content_hash', 'metadata_hash']

        for (const key of forbiddenKeys) {
            if (key in this.metadata) {
                throw new Error(
                    `Metadata cannot contain key ${key} as it is reserved for internal use. Restricted keys: [${forbiddenKeys.join(', ')}]`
                )
            }
        }

        const contentHash = this._hashStringToUUID(this.pageContent)

        try {
            const metadataHash = this._hashNestedDictToUUID(this.metadata)
            this.contentHash = contentHash
            this.metadataHash = metadataHash
        } catch (e) {
            throw new Error(`Failed to hash metadata: ${e}. Please use a dict that can be serialized using json.`)
        }

        this.hash_ = this._hashStringToUUID(this.contentHash + this.metadataHash)

        if (!this.uid) {
            this.uid = this.hash_
        }
    }

    toDocument(): DocumentInterface {
        return new Document({
            pageContent: this.pageContent,
            metadata: this.metadata
        })
    }

    static fromDocument(document: DocumentInterface, uid?: string): _HashedDocument {
        const doc = new this({

View on GitHub (pinned to abe4a8601a)

Solutions

  1. Sanitize metadata to plain JSON-safe values (strings, numbers, booleans, arrays, plain objects, null) before indexing.
  2. Break circular references or replace them with IDs.
  3. Convert class instances to plain objects (e.g. date.toISOString(), bigint.toString()).
  4. Run JSON.stringify(doc.metadata) in a pre-check to catch the offending field early.

Example fix

// before
const docs = [{ pageContent: 'x', metadata: { self: null } }]
docs[0].metadata.self = docs[0].metadata // circular
await index({ docsSource: docs, recordManager, vectorStore })

// after
function toSafeMeta(obj, seen = new WeakSet()) {
  if (obj && typeof obj === 'object') {
    if (seen.has(obj)) return null
    seen.add(obj)
    const out = Array.isArray(obj) ? [] : {}
    for (const [k, v] of Object.entries(obj)) out[k] = toSafeMeta(v, seen)
    return out
  }
  return typeof obj === 'function' ? null : obj
}
const docs = rawDocs.map(d => ({ ...d, metadata: toSafeMeta(d.metadata) }))
Defensive patterns

Strategy: validation

Validate before calling

// Ensure metadata is JSON-safe before indexing
function toSafeMetadata(obj: unknown, seen = new WeakSet()): unknown {
  if (obj === null || typeof obj !== 'object') {
    return typeof obj === 'function' || typeof obj === 'symbol' ? null : obj
  }
  if (seen.has(obj as object)) return null
  seen.add(obj as object)
  if (typeof (obj as any).toJSON === 'function') return (obj as any).toJSON()
  if (typeof (obj as any).toISOString === 'function') return (obj as any).toISOString()
  const out: Record<string, unknown> = {}
  for (const [k, v] of Object.entries(obj as object)) {
    out[k] = toSafeMetadata(v, seen)
  }
  return out
}

const safeDocs = docs.map((d) => ({ ...d, metadata: toSafeMetadata(d.metadata) as Record<string, unknown> }))

Type guard

function isJsonSafe(value: unknown): boolean {
  try { JSON.stringify(value); return true } catch { return false }
}

function hasJsonSafeMetadata(doc: { metadata: unknown }): boolean {
  return isJsonSafe(doc.metadata)
}

Try / catch

try {
  await index({ docsSource, recordManager, vectorStore, options })
} catch (e) {
  if (String(e).includes('Failed to hash metadata')) {
    const sanitized = docs.map((d) => ({ ...d, metadata: toSafeMetadata(d.metadata) }))
    await index({ docsSource: sanitized, recordManager, vectorStore, options })
  } else throw e
}

Prevention

When it happens

Trigger: A Document whose metadata contains a non-JSON-serializable value: a circular reference, a function, a Symbol-keyed or Symbol-valued property, a BigInt, or a class instance without toJSON. JSON.stringify throws and the catch re-throws with this message.

Common situations: Metadata that includes class instances (e.g. a Date object is fine, but a custom class is not), circular references from parent/child links, functions attached as metadata by mistake, or BigInt IDs from a database driver. Documents built from ORM entities that carry back-references.

Related errors


AI-assisted analysis of FlowiseAI/Flowise@abe4a8601a (2026-08-12). Data as JSON: /api/errors/34f1f47a45e0f2f7. Report an issue: GitHub.