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

  1. Delete or move aside the corrupt file and re-run the command to regenerate it (mv session.json session.json.bak)
  2. Check fastmcp version changes — if you downgraded/upgraded, clear the old state
  3. Do not hand-edit state files; use CLI commands to modify state
  4. 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

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


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