PrefectHQ/fastmcp · error · StateFileError
Could not read CLI state: {path.name}
Error message
Could not read CLI state: {path.name} What it means
StateFileError raised by read_state when path.read_text raises OSError after the existence and symlink checks pass. The file is present but unreadable at the OS level, so the CLI cannot load the state and reports the filename in the message.
Source
Thrown at fastmcp_slim/fastmcp/cli/deploy/state.py:166
*,
secret: bool = False,
) -> ModelT | None:
"""Read and validate a versioned JSON state file."""
if not path.exists():
return None
if path.is_symlink():
raise StateFileError(f"CLI state must not be a symbolic link: {path.name}")
if secret:
_restrict_access(path.parent, directory=True)
_restrict_access(path)
try:
return model.model_validate_json(path.read_text(encoding="utf-8"))
except (ValidationError, ValueError):
raise StateFileError(f"CLI state is invalid: {path.name}") from None
except OSError as exc:
raise StateFileError(f"Could not read CLI state: {path.name}") from exc
def write_state(path: Path, data: dict[str, Any]) -> None:
"""Write JSON through a restricted temporary file and atomic replacement."""
_prepare_directory(path.parent)
payload = (json.dumps(data, indent=2, sort_keys=True) + "\n").encode()
descriptor: int | None = None
temporary_path: Path | None = None
try:
descriptor, temporary_name = tempfile.mkstemp(
dir=path.parent,
prefix=f".{path.name}.",
suffix=".tmp",
)
temporary_path = Path(temporary_name)
if os.name != "nt":
os.fchmod(descriptor, 0o600)View on GitHub (pinned to 1f02114297)
Solutions
- Fix ownership/permissions on the file: chown $USER or chmod u+r on the state file (and 0o700 on its directory)
- Stop mixing elevated and normal runs (avoid sudo for CLI commands, or chown the state back afterwards)
- Delete the unreadable file and re-authenticate to regenerate it
- Check disk/health (dmesg) if I/O errors persist
Example fix
// before (root-owned after sudo run) -rw------- root root ~/.fastmcp/state/session.json // after $ sudo chown $USER ~/.fastmcp/state/session.json
Defensive patterns
Strategy: validation
Validate before calling
import os
from pathlib import Path
def assert_readable(path: Path) -> None:
if path.exists() and not os.access(path, os.R_OK):
raise RuntimeError(f"{path} is not readable; fix ownership/permissions") Try / catch
try:
state = load(state_path)
except StateFileError as exc:
if "Could not read" in str(exc):
subprocess.run(["chown", str(os.getuid()), str(state_path)], check=False)
state = load(state_path)
else:
raise Prevention
- Avoid running the CLI with sudo (root-owned 0o600 state is unreadable later)
- After using elevated runs, chown the state directory back to your user
- Keep state on a healthy local disk; investigate repeated I/O errors
- Check file readability after account/machine migrations
When it happens
Trigger: read_state (via load) on a file whose permissions deny the current user read access (e.g. state created under another account, or a prior _restrict_access left it 0o600 owned by root), or an I/O error while reading (failing disk, file deleted between exists() and read).
Common situations: Running the CLI with sudo previously so the state file is now root-owned; different user account after a machine migration; EFS/encrypted-volume errors; race where another process removed the file mid-read.
Related errors
- Could not restrict access to CLI state
- Could not create the CLI state directory
- Could not write CLI state: {path.name}
- Error reading file {self.path}
- Error listing directory {self.path}
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/f7a12af6fa0495d8.
Report an issue: GitHub.