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

  1. Ensure every key in per_file_metadata is a non-empty filename string exactly matching an ingested file's name.
  2. Sanitize the dict client-side before sending: drop or rename empty/None keys.
  3. 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

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


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