PrefectHQ/fastmcp · error · StateFileError

Could not create the CLI state directory

Error message

Could not create the CLI state directory

What it means

StateFileError raised by _prepare_directory when path.mkdir(parents=True, exist_ok=True) fails with OSError. The CLI cannot create (or cannot reach) the directory that holds CLI state, so dependent operations (write_state, state_lock) cannot proceed.

Source

Thrown at fastmcp_slim/fastmcp/cli/deploy/state.py:91

    except (OSError, subprocess.SubprocessError) as exc:
        raise StateFileError("Could not restrict access to CLI state") from exc


def _restrict_access(path: Path, *, directory: bool = False) -> None:
    try:
        if os.name == "nt":
            _restrict_windows_access(path)
        else:
            path.chmod(0o700 if directory else 0o600)
    except OSError as exc:
        raise StateFileError("Could not restrict access to CLI state") from exc


def _prepare_directory(path: Path) -> None:
    try:
        path.mkdir(parents=True, exist_ok=True)
    except OSError as exc:
        raise StateFileError("Could not create the CLI state directory") from exc
    _restrict_access(path, directory=True)


@contextmanager
def state_lock(directory: Path) -> Iterator[None]:
    """Lock related CLI state changes across processes."""
    _prepare_directory(directory)
    lock_path = directory / ".state.lock"
    if lock_path.is_symlink():
        raise StateFileError("The CLI state lock must not be a symbolic link")

    lock_file = None
    try:
        lock_file = lock_path.open("a+b")
        _restrict_access(lock_path)
        if os.name == "nt":
            import msvcrt

View on GitHub (pinned to 1f02114297)

Solutions

  1. Check each path component: a file exists where a directory is needed — remove/rename it or pick a new path
  2. Verify write permission on the nearest existing ancestor of the target directory
  3. Set FASTMCP_STATE_PATH to a writable location (e.g. ~/.fastmcp/state)
  4. Free disk space if the volume is full

Example fix

// before (parent is a file -> mkdir fails)
FASTMCP_STATE_PATH=/home/me/state-file/state
// after
FASTMCP_STATE_PATH=/home/me/.fastmcp/state
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
import os

def ensure_state_dir_writable(raw: str) -> Path:
    path = Path(raw).expanduser()
    for parent in path.parents:
        if parent.exists():
            if not parent.is_dir():
                raise RuntimeError(f"{parent} is a file, blocking directory creation")
            if not os.access(parent, os.W_OK):
                raise RuntimeError(f"{parent} is not writable")
            break
    return path

Try / catch

try:
    with state_lock(state_dir):
        ...
except StateFileError as exc:
    print(f"Set FASTMCP_STATE_PATH to a writable location: {exc}")

Prevention

When it happens

Trigger: Any caller of _prepare_directory (state_lock, write_state) whose configured state directory path cannot be created — e.g. a parent component of the path is an existing file, or the process lacks write permission on the nearest existing parent.

Common situations: FASTMCP_STATE_PATH set to a path whose parent is a file; read-only home directory or disk-full; sandboxed/CI environments with restricted HOME; typo'd absolute path under a non-writable root like /proc or a system-owned directory.

Related errors


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/9dbd671e2919cd40. Report an issue: GitHub.