langflow-ai/langflow · error · HTTPException
Per-file metadata for {filename!r} must be a JSON object.
Error message
Per-file metadata for {filename!r} must be a JSON object. What it means
Raised by validate_file_metadata_map in the knowledge-base upload API when the per-file metadata payload is a JSON object overall, but one of its values (the metadata for a specific filename) is not itself a JSON object. The endpoint validates the file_metadata_map before processing uploads and rejects the whole request with HTTP 422. Each filename key must map to a dict of key/value metadata pairs.
Source
Thrown at src/backend/base/langflow/api/utils/kb_metadata.py:132
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
- Fix the payload so every filename key maps to a JSON object of metadata pairs: {"<filename>": {"key": "value", ...}}
- Verify you are not double-stringifying: if you json.dumps the inner metadata before sending, decode it client-side first
- Check the other 422 guards in the same validator (top-level must be an object, <= KB_METADATA_MAX_KEYS entries, non-empty filename keys) if the error persists
Example fix
// before
file_metadata_map = {"report.pdf": "source=legal"}
// after
file_metadata_map = {"report.pdf": {"source": "legal"}} Defensive patterns
Strategy: validation
Validate before calling
def is_valid_file_metadata_map(payload: str | dict) -> bool:
import json
decoded = json.loads(payload) if isinstance(payload, str) else payload
return (
isinstance(decoded, dict)
and decoded
and all(
isinstance(k, str) and k and isinstance(v, dict)
for k, v in decoded.items()
)
) Type guard
def is_file_metadata_map(v: object) -> bool:
return isinstance(v, dict) and all(
isinstance(k, str) and k and isinstance(m, dict) for k, m in v.items()
) Try / catch
try:
resp = client.post(kb_upload_url, files=files, data={"file_metadata_map": json.dumps(mm)})
except HTTPStatusError as e:
if e.response.status_code == 422:
detail = e.response.json()["detail"]
if "must be a JSON object" in detail:
fix_and_retry(mm) # normalize offending entry to a dict
else:
raise
else:
raise Prevention
- Always build per-file metadata as {filename: {k: v}} in one place, via a typed client helper
- Never json.dumps the inner metadata before nesting it
- Add a client-side schema check mirroring the server's: dict-of-dicts, non-empty keys, entry count under the server limit
When it happens
Trigger: POST to a KB file-upload endpoint with a JSON file_metadata_map whose decoded top-level value is a dict, but where at least one filename entry maps to a string, number, list, or null instead of an object (e.g. {"report.pdf": "category: docs"} or {"a.txt": ["tag"]}).
Common situations: Clients that send metadata as a flat string, a JSON-encoded string inside a string, or reuse a per-file metadata schema from an older API version that accepted scalars; copy-pasting the single-file metadata object directly as the value instead of nesting it under the filename key.
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/174f4fe1c75878c6.
Report an issue: GitHub.