langflow-ai/langflow · warning · HTTPException
Per-file metadata keys must be non-empty filename strings.
Error message
Per-file metadata keys must be non-empty filename strings.
What it means
A 422 from the folder-ingest endpoint when the per_file_metadata mapping has a key that is not a non-empty string. Keys are filenames used to attach metadata to specific ingested files, so empty or non-string keys are rejected during request validation.
Source
Thrown at src/backend/base/langflow/api/v1/knowledge_bases.py:1229
"""
_kb_guard = await _guard_kb_action(current_user=current_user, action=KnowledgeBaseAction.INGEST, kb_name=kb_name)
_assert_kb_not_memory_base(kb_name, _kb_guard.owner_user)
try:
# Validate user-supplied metadata before resolving the KB path so a
# malformed payload responds with 422 rather than 404 if the KB name
# also happens to be wrong.
from langflow.api.utils.kb_metadata import (
validate_user_metadata as _validate_user_metadata,
)
run_user_metadata: dict[str, Any] = {}
if payload.metadata:
run_user_metadata = _validate_user_metadata(dict(payload.metadata))
per_file_user_metadata: dict[str, dict[str, Any]] = {}
if payload.per_file_metadata:
for filename, file_meta in payload.per_file_metadata.items():
if not isinstance(filename, str) or not filename:
raise HTTPException(
status_code=422,
detail="Per-file metadata keys must be non-empty filename strings.",
)
per_file_user_metadata[filename] = _validate_user_metadata(dict(file_meta or {}))
kb_path = _resolve_kb_path(kb_name, _kb_guard.owner_user)
metadata = KBAnalysisHelper.get_metadata(kb_path, fast=False)
if not metadata:
raise HTTPException(
status_code=400,
detail="Knowledge base missing embedding configuration. Please create a new KB or reconfigure it.",
)
model_selection = metadata.get("model_selection") or {
"name": metadata.get("embedding_model"),
"provider": metadata.get("embedding_provider"),
}
if not model_selection.get("name") or not model_selection.get("provider"):View on GitHub (pinned to 976ec789d2)
Solutions
- Ensure every key in per_file_metadata is a non-empty filename string exactly matching an ingested file's name.
- Sanitize the dict client-side before sending: drop or rename empty/None keys.
- If filenames come from os.walk output, filter out non-string or empty entries.
Example fix
# before
per_file = {"": {...}, "report.pdf": {...}}
# after
per_file = {name: meta for name, meta in per_file.items() if isinstance(name, str) and name} Defensive patterns
Strategy: validation
Validate before calling
def sanitize_per_file_metadata(per_file: dict) -> dict[str, dict]:
return {
str(name): meta or {}
for name, meta in per_file.items()
if isinstance(name, str) and name
} Type guard
def is_valid_per_file_metadata(d: object) -> bool:
if not isinstance(d, dict):
return False
return all(isinstance(k, str) and bool(k) for k in d) Prevention
- Build per_file_metadata only from filesystem-derived filename strings.
- Filter empty-string or None keys before serializing the request body.
- Add a unit test asserting every key of the payload is a non-empty string.
When it happens
Trigger: POST /api/v1/knowledge_bases/{kb_name}/ingest/folder with a JSON body whose per_file_metadata object contains a key like "" (empty string) or a non-string key (possible when building the dict with int/None keys before serializing, or hand-writing malformed JSON).
Common situations: Client code constructing per_file_metadata programmatically with Path objects coerced badly, typos in hand-written payloads, or empty-string filenames from upstream file listing code.
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/0ff38fb77160c904.
Report an issue: GitHub.