PrefectHQ/fastmcp · error · StateFileError
CLI state is invalid: {path.name}
Error message
CLI state is invalid: {path.name} What it means
StateFileError raised by read_state when the state file's contents fail pydantic validation (ValidationError) or JSON parsing (ValueError). The file exists but is not a valid instance of the expected versioned model, so the CLI treats the state as unusable. The original error is deliberately suppressed (from None).
Source
Thrown at fastmcp_slim/fastmcp/cli/deploy/state.py:164
path: Path,
model: type[ModelT],
*,
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)View on GitHub (pinned to 1f02114297)
Solutions
- Delete or move aside the corrupt file and re-run the command to regenerate it (mv session.json session.json.bak)
- Check fastmcp version changes — if you downgraded/upgraded, clear the old state
- Do not hand-edit state files; use CLI commands to modify state
- Restore from backup if the state held credentials you need
Example fix
// before
$ cat ~/.fastmcp/state/session.json
{"origin": "https://api" <truncated>
// after
$ mv ~/.fastmcp/state/session.json ~/.fastmcp/state/session.json.bak
$ fastmcp login # rewrites valid state Defensive patterns
Strategy: validation
Validate before calling
import json
from pathlib import Path
def state_file_parses(path: Path) -> bool:
try:
json.loads(path.read_text(encoding="utf-8"))
return True
except (json.JSONDecodeError, UnicodeDecodeError):
return False Try / catch
try:
state = load(state_path)
except StateFileError as exc:
if "invalid" in str(exc):
state_path.rename(state_path.with_suffix(".json.bak"))
state = load(state_path) # regenerate fresh state
else:
raise Prevention
- Never hand-edit CLI state JSON
- Don't kill the CLI mid-write; rely on atomic writes
- Back up state before upgrading/downgrading fastmcp
- If a file is repeatedly corrupt, check disk health (smartctl)
When it happens
Trigger: Calling read_state (via load) when path.read_text returns content that is not parseable JSON or does not match the expected model schema — truncated file, hand-edited JSON, empty file, or state written by an incompatible older/newer fastmcp version.
Common situations: Power loss or crash mid-write leaving a truncated file (older fastmcp without atomic writes); manual editing of state JSON; upgrading/downgrading fastmcp so the schema changed; encoding corruption.
Related errors
- Elicitation responses must be serializable as a JSON object
- CIMD document is not valid JSON: {e}
- Expected integer, got {raw!r}
- Expected number, got {raw!r}
- Expected boolean, got {raw!r}
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/4fa36cf898ab22e0.
Report an issue: GitHub.