langflow-ai/langflow · error · HTTPException

Invalid base directory: {e}

Error message

Invalid base directory: {e}

What it means

HTTP 400: os.path.realpath() raised OSError/ValueError while canonicalising the BASE directory (storage_service.data_dir / "flows" / <user_id>). This is a server-side configuration problem, not a bad client path — the user-supplied fs_path has not even been joined yet.

Source

Thrown at src/backend/base/langflow/api/v1/flows_helpers.py:81

    # Reject directory traversal and null bytes (check normalized path)
    if ".." in normalized_path:
        raise HTTPException(
            status_code=400,
            detail="Invalid fs_path: directory traversal (..) is not allowed",
        )
    if "\x00" in normalized_path:
        raise HTTPException(
            status_code=400,
            detail="Invalid fs_path: null bytes are not allowed",
        )

    # Build and canonicalise the safe base directory path.
    base_dir = storage_service.data_dir / "flows" / str(user_id)
    try:
        base_dir_resolved = os.path.realpath(str(base_dir))
    except (OSError, ValueError) as e:
        raise HTTPException(status_code=400, detail=f"Invalid base directory: {e}") from e

    # Determine if path is absolute (Unix or Windows style)
    is_absolute = normalized_path.startswith("/") or (len(normalized_path) > 1 and normalized_path[1] == ":")

    if is_absolute:
        candidate = normalized_path
    else:
        relative_part = normalized_path.lstrip("/")
        # os.path.join is deliberate here (PTH118) to match CodeQL's sanitiser model.
        candidate = os.path.join(base_dir_resolved, relative_part) if relative_part else base_dir_resolved  # noqa: PTH118

    try:
        resolved_str = os.path.realpath(candidate)
    except (OSError, ValueError) as e:
        raise HTTPException(status_code=400, detail=f"Invalid path: {e}") from e

    # SECURITY: containment check using os.path.realpath + startswith (CodeQL-recognised).
    if resolved_str != base_dir_resolved and not resolved_str.startswith(base_dir_resolved + os.sep):

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Check the LANGFLOW_DATA_DIR (or storage service data_dir) setting on the server and fix/normalise it.
  2. On Windows, enable long-path support (>260 chars) or shorten the data dir.
  3. Verify the data directory and its parents resolve (readlink/realpath) with the same user the backend runs as.
  4. Recreate the flows/<user_id> directory if it was replaced by a broken symlink.

Example fix

# before
LANGFLOW_DATA_DIR="/data/flows\u0000"  # corrupted env
# after
LANGFLOW_DATA_DIR=/data/flows
Defensive patterns

Strategy: validation

Validate before calling

python -c "import os; print(os.path.realpath('PATH_TO_DATA_DIR'))"  # run as the backend user before startup

Try / catch

try: create_flow(...) except HTTPException as e: if e.status_code == 400 and 'base directory' in e.detail: alert_ops_bad_datadir(); raise

Prevention

When it happens

Trigger: The configured LANGFLOW_DATA_DIR (or the drive it lives on) is invalid on the host: extremely long path on Windows (OSError), a data_dir containing embedded NUL bytes from a mis-set env var, or a filesystem error while resolving symlinks in the base directory.

Common situations: LANGFLOW_DATA_DIR env var set to a bad value (trailing NUL from a script, nonexistent drive letter on Windows, path exceeding MAX_PATH without long-path support); Docker volume whose underlying mount is broken; a symlink loop in the data directory tree.

Related errors


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