FlowiseAI/Flowise · error · Error

Metadata cannot contain key

Error message

Metadata cannot contain key ${key} as it is reserved for internal use. Restricted keys: [${forbiddenKeys.join(', ')}]

What it means

Thrown by _HashedDocument.calculateHashes() when document metadata contains one of the reserved internal keys: 'hash_', 'content_hash', or 'metadata_hash'. These keys are written by the indexer itself to track document identity; allowing user metadata to set them would collide with the indexing bookkeeping and corrupt deduplication. The check runs before hashes are computed.

Solutions

  1. Rename the conflicting key in your metadata before indexing (e.g. 'content_hash' → 'source_content_hash').
  2. Strip reserved keys in a pre-indexing transform: delete doc.metadata.hash_ etc.
  3. Namespace your metadata under a prefix to avoid future collisions (e.g. 'user_hash_').
  4. Validate metadata keys against the reserved list at the document-ingestion boundary so the error never reaches the indexer.

Example fix

// before
const docs = [{ pageContent: 'hello', metadata: { content_hash: 'abc', source: 'x' } }]
await index({ docsSource: docs, recordManager, vectorStore, options: { cleanup: 'incremental', sourceIdKey: 'source' } })

// after
const RESERVED = ['hash_', 'content_hash', 'metadata_hash']
const docs = rawDocs.map(d => ({
  ...d,
  metadata: Object.fromEntries(Object.entries(d.metadata).filter(([k]) => !RESERVED.includes(k)))
}))
Defensive patterns

Strategy: validation

Validate before calling

const RESERVED_META_KEYS = ['hash_', 'content_hash', 'metadata_hash']

function stripReservedMetadata<T extends { metadata: Record<string, unknown> }>(doc: T): T {
  const cleaned = Object.fromEntries(
    Object.entries(doc.metadata).filter(([k]) => !RESERVED_META_KEYS.includes(k))
  )
  return { ...doc, metadata: cleaned }
}

const safeDocs = docs.map(stripReservedMetadata)

Type guard

function hasReservedMeta(meta: Record<string, unknown>): boolean {
  return ['hash_', 'content_hash', 'metadata_hash'].some((k) => k in meta)
}

Try / catch

try {
  await index({ docsSource, recordManager, vectorStore, options })
} catch (e) {
  if (String(e).includes('reserved for internal use')) {
    const cleaned = docs.map(stripReservedMetadata)
    await index({ docsSource: cleaned, recordManager, vectorStore, options })
  } else throw e
}

Prevention

When it happens

Trigger: Passing a Document to index() whose metadata object has a top-level key named 'hash_', 'content_hash', or 'metadata_hash'. The forbidden loop at lines 80-86 scans the metadata keys and throws on the first collision. This happens during _HashedDocument.fromDocument() → calculateHashes() for every document in every batch.

Common situations: User-uploaded documents whose metadata schema happens to use these key names. Migrating from another indexing system that used 'content_hash'. Documents enriched by a pipeline that computes its own hashes and stores them in metadata. A search/indexing feature that lets end-users attach arbitrary metadata.

Understand the failure class

Related errors


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

Appendix: source

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

    metadataHash?: string

    pageContent: string

    metadata: Metadata

    constructor(fields: HashedDocumentArgs) {
        this.uid = fields.uid
        this.pageContent = fields.pageContent
        this.metadata = fields.metadata
    }

    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) {

View on GitHub (pinned to abe4a8601a)