langflow-ai/langflow · warning · HTTPException

Metadata exceeds the {KB_METADATA_MAX_KEYS} key limit.

Error message

Metadata exceeds the {KB_METADATA_MAX_KEYS} key limit.

What it means

A metadata object may contain at most KB_METADATA_MAX_KEYS = 16 keys. The count check runs immediately after the object-shape check and rejects the entire payload with 422 when exceeded, because every key/value pair is duplicated onto every chunk of the ingested file in the vector store.

Source

Thrown at src/backend/base/langflow/api/utils/kb_metadata.py:78

                raise HTTPException(status_code=422, detail=msg)
        return
    msg = f"Metadata value for '{key}' must be a string, number, bool, or string array; got {type(value).__name__}."
    raise HTTPException(status_code=422, detail=msg)


def validate_user_metadata(metadata: dict[str, Any]) -> dict[str, Any]:
    """Enforce the user-metadata contract on a decoded dict.

    Returns the same dict (a shallow copy is *not* made — callers may mutate
    safely once validation passes). Raises :class:`HTTPException` with a 422
    status on any violation so FastAPI surfaces an inline error.
    """
    if not isinstance(metadata, dict):
        msg = "Metadata must be a JSON object."
        raise HTTPException(status_code=422, detail=msg)
    if len(metadata) > KB_METADATA_MAX_KEYS:
        msg = f"Metadata exceeds the {KB_METADATA_MAX_KEYS} key limit."
        raise HTTPException(status_code=422, detail=msg)
    for key, value in metadata.items():
        if not isinstance(key, str) or not _is_valid_key(key):
            msg = (
                f"Metadata key {key!r} is invalid: must be 1-{KB_METADATA_MAX_KEY_LENGTH} "
                "lowercase alphanumeric or underscore characters."
            )
            raise HTTPException(status_code=422, detail=msg)
        if key in KB_METADATA_RESERVED_KEYS:
            msg = f"Metadata key '{key}' is reserved for ingestion-internal use."
            raise HTTPException(status_code=422, detail=msg)
        _validate_value(key, value)
    return metadata


def parse_user_metadata(raw: str | None) -> dict[str, Any]:
    """Decode + validate the ``metadata`` form field. Empty/None → ``{}``."""
    if not raw:
        return {}

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Cut the dict to the 16 keys you actually filter on client-side (prioritize keys used in queries).
  2. Move rarely-filtered fields into the document content or an external store keyed by file id.
  3. Use compact keys — but note key length is separately capped at 32 chars, so abbreviate within that.
  4. Programmatically enforce: assert len(meta) <= 16 before building the multipart form.

Example fix

# before
metadata = extracted  # 30 keys -> 422

# after
FILTER_KEYS = ['project', 'doctype', 'year']
metadata = {k: extracted[k] for k in FILTER_KEYS if k in extracted}  # <=16
Defensive patterns

Strategy: validation

Validate before calling

from langflow.utils.kb_constants import KB_METADATA_MAX_KEYS as MAXK

def cap_keys(meta: dict, priority: list[str]) -> dict:
    keep = [k for k in priority if k in meta][:MAXK]
    keep += [k for k in meta if k not in keep and len(keep) < MAXK]
    return {k: meta[k] for k in keep}

Type guard

def within_key_limit(meta) -> bool:
    return isinstance(meta, dict) and len(meta) <= 16

Try / catch

try:
    validate_user_metadata(meta)
except HTTPException as e:
    if e.status_code == 422 and 'key limit' in e.detail:
        meta = cap_keys(meta, PRIORITY_KEYS); validate_user_metadata(meta)
    else:
        raise

Prevention

When it happens

Trigger: metadata (or any inner dict of per_file_metadata) is a JSON object with 17+ keys. The file-level count check for per_file_metadata (KB_METADATA_MAX_KEYS files) is a separate earlier error; this one counts keys inside a single metadata dict.

Common situations: Auto-extracted metadata (entities, attributes, dates, ...) with unbounded key counts; migrating a wide schema (CRM records, 30+ columns) into KB metadata; additive development where teams keep piling fields until the cap is hit.

Related errors


AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14). Data as JSON: /api/errors/f920d4113839bd4d. Report an issue: GitHub.