langflow-ai/langflow · error · UserComponentError

str(exc)

Error message

str(exc)

What it means

Raised when _resolve_components_dir's call to FileSystemToolComponent._validate_root() raises PermissionError, and the message is re-wrapped as UserComponentError(str(exc)). Two documented causes: (1) AUTO_LOGIN=False and no user_id was supplied — the sandbox resolver refuses to pick a shared root in that mode; (2) sandbox configuration or disk failure inside the resolver. The original message text is preserved verbatim.

Source

Thrown at src/backend/base/langflow/agentic/services/user_components.py:264

def _resolve_components_dir(*, user_id: str | None) -> Path:
    """Resolve and create ``<sandbox>/.components/`` for the given user.

    Reuses the FS tool's authoritative sandbox resolver so the hash
    function, pepper handling, AUTO_LOGIN dispatch, and no-user refusal
    stay in one place. The reserved-segment guard does NOT apply here —
    this helper is the privileged writer that the guard is protecting.
    """
    component = FileSystemToolComponent()
    if user_id is not None:
        component._user_id = user_id  # noqa: SLF001 — privileged binding seam
    try:
        sandbox_root = component._validate_root()  # noqa: SLF001
    except PermissionError as exc:
        # PermissionError from _validate_root happens in two cases:
        # 1. AUTO_LOGIN=False and no user_id → translate to our domain error.
        # 2. Sandbox config / disk failure → re-wrap so callers see the
        #    same single-class refusal envelope.
        raise UserComponentError(str(exc)) from exc

    components_dir = sandbox_root / ".components"
    try:
        components_dir.mkdir(parents=True, exist_ok=True)
    except OSError as exc:
        msg = f"Cannot create .components directory: {exc.strerror or exc}"
        raise UserComponentError(msg) from exc
    return components_dir


def _atomic_write_text(target: Path, text: str) -> None:
    """Write ``text`` to ``target`` via a tmp file + os.replace rename.

    On any failure, removes the tmp file so the directory never
    accumulates stray ``.tmp`` artifacts. ``os.replace`` is atomic on
    POSIX and on Windows (since Python 3.3) when source and dest are on
    the same filesystem — which they are here, both inside the user's
    sandbox.

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Pass a real user_id when AUTO_LOGIN=False — each user gets their own hashed sandbox directory.
  2. If a user_id was passed, inspect the wrapped PermissionError message: it names the actual sandbox config problem.
  3. Verify the sandbox base directory exists and is writable by the backend process, and that the pepper file is intact.

Example fix

# before (AUTO_LOGIN=False)
register_user_component(user_id=None, class_name="MyTool", code=src)

# after
register_user_component(user_id=str(current_user.id), class_name="MyTool", code=src)
Defensive patterns

Strategy: validation

Validate before calling

def can_resolve_user_sandbox(user_id: str | None, auto_login: bool) -> bool:
    return user_id is not None or auto_login

Try / catch

try:
    register_user_component(user_id=user_id, class_name=name, code=src)
except UserComponentError as e:
    if "permission" in str(e).lower() or "user" in str(e).lower():
        log_config_problem(str(e))  # message is the original PermissionError text

Prevention

When it happens

Trigger: Calling register_user_component(user_id=None) while the deployment runs with AUTO_LOGIN=False; or a corrupted/missing sandbox base dir, unreadable pepper file, or permission problem on the configured BASE_DIR.

Common situations: Background/worker contexts where no authenticated user is bound; env var LANGFLOW_AUTO_LOGIN toggled between environments; sandbox root moved or its permissions changed after deployment.

Related errors


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