langflow-ai/langflow · error · HTTPException

Invalid file path format

Error message

Invalid file path format

What it means

HTTP 400 from validate_public_files when an entry does not match _PUBLIC_FILE_PATH_RE: ^({uuid})/([^/\\]+)$. The reference must be exactly a flow UUID, a single slash, and a basename containing no further separators — no absolute paths, no query strings, no subdirectories, no filenames with slashes.

Source

Thrown at src/backend/base/langflow/api/utils/flow_utils.py:166

def validate_public_files(files: list[str] | None, source_flow_id: uuid.UUID) -> None:
    """Reject file references that aren't ``{source_flow_id}/{basename}``.

    Mitigates GHSA-rcjh-r59h-gq37: an unauthenticated build must not be
    able to address files outside its own flow's storage namespace.
    Called from any endpoint that accepts caller-supplied file references
    under a public-access boundary.
    """
    if not files:
        return
    expected_flow_id = str(source_flow_id).lower()
    for entry in files:
        if not isinstance(entry, str) or not entry:
            raise HTTPException(status_code=400, detail="Invalid file entry")
        if any(token in entry for token in _PUBLIC_FILE_REJECTED_SUBSTRINGS):
            raise HTTPException(status_code=400, detail="Invalid file path")
        match = _PUBLIC_FILE_PATH_RE.match(entry)
        if not match:
            raise HTTPException(status_code=400, detail="Invalid file path format")
        flow_id_segment, basename = match.group(1), match.group(2)
        if flow_id_segment.lower() != expected_flow_id:
            raise HTTPException(status_code=400, detail="File not in this flow's namespace")
        if basename in (".", ".."):
            raise HTTPException(status_code=400, detail="Invalid filename")


def compute_virtual_flow_id(
    identifier: str | uuid.UUID,
    flow_id: uuid.UUID,
    *,
    principal_type: Literal["user", "client"] | None = None,
) -> uuid.UUID:
    """Compute a deterministic virtual flow ID for session/message isolation.

    Args:
        identifier: A unique identifier (user_id for authenticated users, client_id for anonymous).
        flow_id: The original flow ID.

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Always send the full canonical form: lowercase flow UUID + '/' + filename as returned by the upload endpoint
  2. Flatten any subdirectory structure — upload files individually and reference them by basename under the flow id
  3. Validate client-side with the same regex before submit

Example fix

import re
PUB = re.compile(r'^([0-9a-fA-F-]{36})/([^/\\]+)$')
# before
{ "files": ["uploads/data.csv"] }  # 400 Invalid file path format
# after
{ "files": [PUB and "3fa85f64-5717-4562-b3fc-2c963f66afa6/data.csv"] }
Defensive patterns

Strategy: type-guard

Validate before calling

const PUB = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\/[^/\\]+$/;
const files = raw.filter(f => PUB.test(f));

Type guard

const UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
const isPublicFilePath = (f) => typeof f === 'string' && f.includes('/') && UUID.test(f.split('/')[0]) && /^[^/\\]+$/.test(f.slice(f.indexOf('/') + 1));

Prevention

When it happens

Trigger: Sending 'data.csv' (missing flow prefix), '/abs/path/data.csv', '{uuid}/sub/dir/file.csv' (nested), '{uuid}/file.csv?x=1', or a non-UUID flow prefix like 'myflow/file.csv'.

Common situations: Clients passing just the basename after upload and assuming the server infers the flow; folder-upload UIs preserving subdirectory structure in names; template code hardcoding relative paths.

Related errors


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