langflow-ai/langflow · error · UserComponentError

Cannot create .components directory: {exc.strerror or exc}

Error message

Cannot create .components directory: {exc.strerror or exc}

What it means

Raised when os.makedirs-style creation of <sandbox>/<user-hash>/.components fails with an OSError; the message includes the OS strerror (e.g. 'Permission denied', 'No space left on device', 'Read-only file system'). This is an environment-level failure, not an input validation issue.

Source

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

    """
    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.
    """
    # Use tempfile inside the SAME directory so os.replace stays
    # cross-device-safe (replace requires source+dest on the same FS).
    tmp_fd, tmp_name = tempfile.mkstemp(prefix=f"{target.stem}.", suffix=".py.tmp", dir=str(target.parent))
    tmp_path = Path(tmp_name)
    try:
        with os.fdopen(tmp_fd, "w", encoding="utf-8") as f:

View on GitHub (pinned to 976ec789d2)

Solutions

  1. Check the strerror in the message: 'Permission denied' -> chown/chmod the sandbox base dir for the backend user; 'No space left on device' -> free disk or expand the volume.
  2. Confirm the sandbox base dir is on a writable filesystem and not shadowed by a file.
  3. After fixing, retry the registration — the write is idempotent (mkdir exist_ok=True).
Defensive patterns

Strategy: fallback

Validate before calling

from pathlib import Path

def components_dir_writable(base: Path) -> bool:
    d = base / ".components"
    try:
        d.mkdir(parents=True, exist_ok=True)
        probe = d / ".probe"
        probe.write_text("")
        probe.unlink()
        return True
    except OSError:
        return False

Try / catch

try:
    register_user_component(user_id=uid, class_name=name, code=src)
except UserComponentError as e:
    if str(e).startswith("Cannot create .components"):
        alert_ops_disk_or_permissions(str(e))  # contains OS strerror
        # degrade gracefully: run component without persisting

Prevention

When it happens

Trigger: The sandbox root resolves successfully but the process lacks write permission on it, the volume is full, the path crosses a read-only mount, or a file exists where the .components directory should go.

Common situations: Containers running as a non-root user against a host-mounted volume with wrong ownership; disk-full incidents; containerized deployments with a read-only or mis-mounted sandbox volume.

Related errors


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