langflow-ai/langflow · error · HTTPException

Invalid file entry

Error message

Invalid file entry

What it means

HTTP 400 from validate_public_files when a file entry in the files list is not a non-empty string. This validator guards the unauthenticated/public build boundary (GHSA-rcjh-r59h-gq37): every caller-supplied file reference must be a proper string in the form {source_flow_id}/{basename}.

Source

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

    r"^([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})/([^/\\]+)$"
)
_PUBLIC_FILE_REJECTED_SUBSTRINGS = ("\x00", "..", "\\")


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:

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Send only string entries formatted as '{source_flow_id}/{basename}'
  2. Omit the files field entirely or send an empty list when no files are needed — validate_public_files returns early on falsy/empty
  3. Sanitize client-side: files = [f for f in files if isinstance(f, str) and f]

Example fix

// before
{ "files": [null, "uuid-.../data.csv"] }  // 400 Invalid file entry
// after
{ "files": ["uuid-.../data.csv"] }
Defensive patterns

Strategy: validation

Validate before calling

const cleanFiles = (files) => (files ?? []).filter(f => typeof f === 'string' && f.length > 0);

Type guard

const isValidFileEntry = (f) => typeof f === 'string' && f.length > 0 && /^[0-9a-fA-F-]{36}\/[^/\\]+$/.test(f);

Prevention

When it happens

Trigger: Submitting a public/unauthenticated build request whose files array contains null, 0, empty string '', or a non-string value (number, object) instead of a 'flow-uuid/filename' string.

Common situations: Client SDKs serializing optional file fields as null instead of omitting them; form inputs producing empty strings; JSON built dynamically where a filename variable is undefined.

Related errors


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