langflow-ai/langflow · warning · HTTPException
Per-file metadata exceeds the {KB_METADATA_MAX_KEYS} file li
Error message
Per-file metadata exceeds the {KB_METADATA_MAX_KEYS} file limit. What it means
parse_per_file_metadata caps the number of per-file override entries at KB_METADATA_MAX_KEYS = 16 files. A valid-JSON object keyed by filename with more than 16 entries is rejected with 422 before any inner validation runs — mirroring the run-level 16-key cap since each entry expands into per-chunk metadata.
Source
Thrown at src/backend/base/langflow/api/utils/kb_metadata.py:124
"""Decode + validate the ``per_file_metadata`` form field.
Shape: ``{filename: {metadata_dict}, ...}``. Each inner dict goes through
the same validator as run-level metadata, so per-file overrides obey the
same key/value rules. Empty/None → ``{}``.
"""
if not raw:
return {}
try:
decoded = json.loads(raw)
except json.JSONDecodeError as exc:
msg = f"Per-file metadata is not valid JSON: {exc.msg}"
raise HTTPException(status_code=422, detail=msg) from exc
if not isinstance(decoded, dict):
msg = "Per-file metadata must be a JSON object keyed by filename."
raise HTTPException(status_code=422, detail=msg)
if len(decoded) > KB_METADATA_MAX_KEYS:
msg = f"Per-file metadata exceeds the {KB_METADATA_MAX_KEYS} file limit."
raise HTTPException(status_code=422, detail=msg)
out: dict[str, dict[str, Any]] = {}
for filename, file_metadata in decoded.items():
if not isinstance(filename, str) or not filename:
msg = "Per-file metadata keys must be non-empty filename strings."
raise HTTPException(status_code=422, detail=msg)
if not isinstance(file_metadata, dict):
msg = f"Per-file metadata for {filename!r} must be a JSON object."
raise HTTPException(status_code=422, detail=msg)
out[filename] = validate_user_metadata(file_metadata)
return out
View on GitHub (pinned to 976ec789d2)
Solutions
- Limit overrides to the files that actually need them (<=16) and put the rest in run-level metadata.
- Split the upload into multiple ingest requests, each with <=16 per-file overrides.
- Compute the cap from the same constant the server uses (langflow.utils.kb_constants.KB_METADATA_MAX_KEYS) rather than hardcoding, so a client/server mismatch cannot surprise you.
- If every file needs distinct metadata, per-request batching by metadata group is usually the cleanest model.
Example fix
# before
per_file = {f.name: meta_for(f) for f in all_files} # 50 files -> 422
# after
BATCH = 16
for i in range(0, len(all_files), BATCH):
chunk = all_files[i:i+BATCH]
submit(files=chunk, per_file_metadata={f.name: meta_for(f) for f in chunk}) Defensive patterns
Strategy: validation
Validate before calling
from langflow.utils.kb_constants import KB_METADATA_MAX_KEYS as MAXK
def batch_per_file(per_file: dict, files: list):
for i in range(0, len(files), MAXK):
batch = files[i:i+MAXK]
yield batch, {f: per_file[f] for f in batch if f in per_file} Type guard
def within_file_limit(per_file) -> bool:
return isinstance(per_file, dict) and len(per_file) <= 16 Try / catch
try:
parse_per_file_metadata(raw)
except HTTPException as e:
if e.status_code == 422 and 'file limit' in e.detail:
trimmed = dict(list(per_file.items())[:16])
raw = json.dumps(trimmed)
parse_per_file_metadata(raw)
else:
raise Prevention
- Batch uploads so each request carries <=16 per-file overrides.
- Import KB_METADATA_MAX_KEYS rather than hardcoding 16.
- Put common metadata at run level; keep per-file entries for true exceptions.
When it happens
Trigger: per_file_metadata JSON object with 17+ filename keys. Fires before the per-entry checks, so even if every inner dict is perfect, an oversize map is rejected whole. Note the run-level metadata object has the same numeric cap (error 152) but a different message text.
Common situations: Batch-uploading a directory of 50 files with one ingest request and per-file overrides for each; auto-generating overrides for every file in a folder; pipelines that grew incrementally past the cap without noticing.
Related errors
- Metadata value for '{key}' exceeds {KB_METADATA_MAX_VALUE_LE
- Metadata array '{key}' exceeds {KB_METADATA_MAX_ARRAY_LENGTH
- Metadata array entry under '{key}' exceeds {KB_METADATA_MAX_
- Metadata exceeds the {KB_METADATA_MAX_KEYS} key limit.
- Metadata array '{key}' must contain only strings.
AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14).
Data as JSON: /api/errors/c519b7eb45cb419c.
Report an issue: GitHub.