PrefectHQ/fastmcp · error · ValueError
interval_ms must be positive
Error message
interval_ms must be positive
What it means
A ValueError raised in the PingMiddleware constructor when interval_ms is zero or negative. The middleware pings active sessions on a timer, so a non-positive interval would spin or be meaningless; construction is rejected immediately.
Source
Thrown at fastmcp_slim/fastmcp/server/middleware/ping.py:39
from fastmcp import FastMCP
from fastmcp.server.middleware import PingMiddleware
mcp = FastMCP("MyServer")
mcp.add_middleware(PingMiddleware(interval_ms=5000))
```
"""
def __init__(self, interval_ms: int = 30000):
"""Initialize ping middleware.
Args:
interval_ms: Interval between pings in milliseconds (default: 30000)
Raises:
ValueError: If interval_ms is not positive
"""
if interval_ms <= 0:
raise ValueError("interval_ms must be positive")
self.interval_ms = interval_ms
self._active_sessions: set[int] = set()
self._lock = anyio.Lock()
async def on_message(self, context: MiddlewareContext, call_next: CallNext) -> Any:
"""Start ping task on first message from a connection."""
if (
context.fastmcp_context is None
or context.fastmcp_context.request_context is None
):
return await call_next(context)
session = context.fastmcp_context.session
# SDK v2 constructs a ServerSession per request; the stable per-connection
# identity lives on the underlying Connection. Key the keepalive loop off
# it so one ping task runs for the whole connection and is torn down when
# the connection closes.
connection = getattr(session, "_connection", None)View on GitHub (pinned to 1f02114297)
Solutions
- Pass a positive interval_ms (default is 30000).
- If the value comes from config/env, validate or clamp it before constructing the middleware.
Example fix
// before
interval = int(os.getenv("PING_INTERVAL_MS", "0"))
mw = PingMiddleware(interval_ms=interval) # ValueError
// after
interval = max(int(os.getenv("PING_INTERVAL_MS", "30000")), 1)
mw = PingMiddleware(interval_ms=interval) Defensive patterns
Strategy: validation
Validate before calling
interval_ms = int(os.getenv("PING_INTERVAL_MS", "30000"))
assert interval_ms > 0, f"PING_INTERVAL_MS must be positive, got {interval_ms}"
mw = PingMiddleware(interval_ms=interval_ms) Try / catch
try:
mw = PingMiddleware(interval_ms=interval_ms)
except ValueError as e:
logging.warning("bad ping interval, using default: %s", e)
mw = PingMiddleware() Prevention
- Never default interval config values to 0; use the library default (30000).
- Clamp parsed env/config integers with max(value, 1).
- Add a config schema check that rejects non-positive durations at load time.
- Watch unit conversions (seconds→milliseconds) for zero-producing defaults.
When it happens
Trigger: Instantiating PingMiddleware(interval_ms=0) or PingMiddleware(interval_ms=-100), e.g. from a computed or misconfigured config value (0 from an unset env var parsed as int).
Common situations: Environment variable or YAML config supplying 0 for the interval; arithmetic like ms = seconds * 1000 where seconds defaulted to 0; copying a sample config with a placeholder 0.
Related errors
- max_size must be positive, got {max_size}
- mode must be 'legacy', 'auto', or one of {list(MODERN_PROTOC
- a custom cache store requires CacheConfig.target_id for Fast
- ClientGroup requires at least one client
- Protocol mode for server {name!r} must be a string
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/ba5508736761d443.
Report an issue: GitHub.