langflow-ai/langflow · warning · HTTPException
Metadata key '{key}' is reserved for ingestion-internal use.
Error message
Metadata key '{key}' is reserved for ingestion-internal use. What it means
Eight metadata keys are reserved for the ingestion pipeline itself (KB_METADATA_RESERVED_KEYS: source, file_name, chunk_index, total_chunks, ingested_at, job_id, source_type, source_metadata). If a user-supplied metadata dict uses any of them it is rejected with 422, because a user value would silently overwrite the ingestion-internal tag and break the chunks-browser filters keyed off them.
Source
Thrown at src/backend/base/langflow/api/utils/kb_metadata.py:88
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 {}
try:
decoded = json.loads(raw)
except json.JSONDecodeError as exc:
msg = f"Metadata is not valid JSON: {exc.msg}"
raise HTTPException(status_code=422, detail=msg) from exc
return validate_user_metadata(decoded)
def parse_per_file_metadata(raw: str | None) -> dict[str, dict[str, Any]]:
"""Decode + validate the ``per_file_metadata`` form field.View on GitHub (pinned to 976ec789d2)
Solutions
- Rename your key to a non-reserved equivalent: 'origin', 'upstream_source', 'display_name', 'original_filename', etc. (still snake_case <=32).
- To derive per-file values, use per_file_metadata with non-reserved keys — the pipeline's own file_name is populated automatically.
- Keep a client-side denylist mirroring KB_METADATA_RESERVED_KEYS and strip/rename collisions before submit.
- If you truly need to override ingestion tags, that is not supported at the API boundary — file a feature request instead of working around it.
Example fix
# before
metadata = {"source": "crm", "file_name": f} # 422 reserved
# after
metadata = {"origin": "crm", "original_filename": f} Defensive patterns
Strategy: validation
Validate before calling
from langflow.utils.kb_constants import KB_METADATA_RESERVED_KEYS
def rename_reserved(meta: dict, mapping: dict) -> dict:
return {mapping.get(k, k): v for k, v in meta.items() if k not in KB_METADATA_RESERVED_KEYS or k in mapping} Type guard
def free_of_reserved_keys(meta) -> bool:
return not (set(meta) & KB_METADATA_RESERVED_KEYS) Try / catch
try:
validate_user_metadata(meta)
except HTTPException as e:
if e.status_code == 422 and 'reserved for ingestion-internal use' in e.detail:
meta = rename_reserved(meta, {'source': 'origin', 'file_name': 'original_filename'})
validate_user_metadata(meta)
else:
raise Prevention
- Mirror KB_METADATA_RESERVED_KEYS as a client-side denylist.
- Rename 'source'->'origin', 'file_name'->'original_filename' by convention.
- Remember the pipeline populates those tags itself — you never need to set them.
When it happens
Trigger: metadata or per_file_metadata contains e.g. {"source": "cms"} or {"file_name": "renamed.pdf"}. The reserved set is a frozenset in kb_constants.py; matching is exact and case-sensitive (so 'Source' instead fails the key-charset rule with error 153).
Common situations: Natural naming collisions — pipelines almost always want 'source' or 'file_name' as a user field; porting existing document metadata schemas; per-file overrides trying to rename the displayed filename.
Related errors
- Metadata value for '{key}' exceeds {KB_METADATA_MAX_VALUE_LE
- Metadata array '{key}' exceeds {KB_METADATA_MAX_ARRAY_LENGTH
- Metadata array '{key}' must contain only strings.
- Metadata array entry under '{key}' exceeds {KB_METADATA_MAX_
- Metadata value for '{key}' must be a string, number, bool, o
AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14).
Data as JSON: /api/errors/b23cfc3a1d3ebf3b.
Report an issue: GitHub.