{"record":{"id":"f4874bdbb3fc0563","repo":"PrefectHQ/fastmcp","slug":"could-not-lock-cli-state","errorCode":null,"errorMessage":"Could not lock CLI state","messagePattern":"Could not lock CLI state","errorType":"exception","errorClass":"StateFileError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/cli/deploy/state.py","lineNumber":125,"sourceCode":"        if os.name == \"nt\":\n            import msvcrt\n\n            if lock_path.stat().st_size == 0:\n                lock_file.write(b\"\\0\")\n                lock_file.flush()\n            lock_file.seek(0)\n            msvcrt.locking(lock_file.fileno(), msvcrt.LK_LOCK, 1)\n        else:\n            import fcntl\n\n            fcntl.flock(lock_file.fileno(), fcntl.LOCK_EX)\n    except (OSError, StateFileError) as exc:\n        if lock_file is not None:\n            with suppress(OSError):\n                lock_file.close()\n        if isinstance(exc, StateFileError):\n            raise\n        raise StateFileError(\"Could not lock CLI state\") from exc\n\n    try:\n        yield\n    finally:\n        if os.name == \"nt\":\n            import msvcrt\n\n            with suppress(OSError):\n                lock_file.seek(0)\n                msvcrt.locking(lock_file.fileno(), msvcrt.LK_UNLCK, 1)\n        else:\n            import fcntl\n\n            with suppress(OSError):\n                fcntl.flock(lock_file.fileno(), fcntl.LOCK_UN)\n        with suppress(OSError):\n            lock_file.close()\n","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/cli/deploy/state.py#L107-L143","documentation":"StateFileError raised by state_lock when acquiring the cross-process advisory lock fails with an OSError (StateFileError from _restrict_access is re-raised unchanged). The CLI cannot guarantee exclusive access to CLI state, so it aborts rather than risking concurrent corruption.","triggerScenarios":"Entering state_lock when lock_path.open('a+b') raises OSError (directory not writable, too many open files) or the platform flock/LockFileEx call fails — e.g. a second process holds an incompatible lock or the filesystem does not support locking.","commonSituations":"Another fastmcp CLI process already holds the lock (stuck/hung process); state directory on an NFS/SMB share without working advisory locks; ulimit -n too low; antivirus holding the file open on Windows.","solutions":["Find and terminate the stale process holding the lock (lsof <state-dir>/.state.lock), then retry","Move FASTMCP_STATE_PATH off network filesystems (NFS/SMB) to a local disk","Raise the open-file limit (ulimit -n) if it is exhausted","Remove a leftover .state.lock only after confirming no CLI process is running"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"import subprocess\nresult = subprocess.run([\"lsof\", str(state_dir / \".state.lock\")], capture_output=True)\nif result.stdout:\n    raise RuntimeError(\"Lock held by another process; terminate it first\")","typeGuard":null,"tryCatchPattern":"import time\n\nfor attempt in range(5):\n    try:\n        with state_lock(state_dir):\n            ...\n        break\n    except StateFileError:\n        if attempt == 4:\n            raise\n        time.sleep(0.5 * (attempt + 1))","preventionTips":["Close hung CLI processes before retrying (lsof the lock file)","Keep FASTMCP_STATE_PATH off NFS/SMB where advisory locks are unreliable","Raise ulimit -n if you run many concurrent CLI operations","Remove leftover .state.lock only when no CLI process is running"],"tags":["lockfile","concurrency","filesystem"],"backgroundTag":"file-lock-contention","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}