{"record":{"id":"6ef934afa29d77c2","repo":"PrefectHQ/fastmcp","slug":"cache-scope-requires-cache-ttl-a-scope-without-a","errorCode":null,"errorMessage":"cache_scope requires cache_ttl; a scope without a TTL does not enable caching","messagePattern":"cache_scope requires cache_ttl; a scope without a TTL does not enable caching","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/caching.py","lineNumber":50,"sourceCode":") -> dict[CacheableMethod, CacheHint] | None:\n    \"\"\"Build the per-method `CacheHint` map for the SDK low-level server.\n\n    `cache_ttl` is in seconds and is converted to the wire's milliseconds. When\n    `cache_ttl` is `None` the server emits no hint, so its wire output is\n    identical to a server that never set one; a `cache_scope` given without a\n    `cache_ttl` is meaningless (the client gates caching on the presence of a\n    TTL) and is rejected rather than silently ignored.\n\n    Returns `None` when no hint is set, or a map applying the same hint to every\n    SDK-cacheable method otherwise.\n\n    Raises:\n        ValueError: If `cache_ttl` is not positive, or if `cache_scope` is set\n            without `cache_ttl`.\n    \"\"\"\n    if cache_ttl is None:\n        if cache_scope is not None:\n            raise ValueError(\n                \"cache_scope requires cache_ttl; a scope without a TTL does not \"\n                \"enable caching\"\n            )\n        return None\n    if cache_ttl <= 0:\n        raise ValueError(f\"cache_ttl must be a positive integer, got {cache_ttl}\")\n    hint = CacheHint(ttl_ms=cache_ttl * 1000, scope=cache_scope or \"private\")\n    return dict.fromkeys(get_args(CacheableMethod), hint)\n","sourceCodeStart":32,"sourceCodeEnd":59,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/caching.py#L32-L59","documentation":"build_cache_hints raises ValueError when cache_scope is provided to FastMCP(...) but cache_ttl is None. The client gates caching on the presence of a TTL, so a scope alone would be silently meaningless — the library rejects it instead of ignoring it.","triggerScenarios":"FastMCP(cache_scope=\"public\") without cache_ttl; programmatically calling build_cache_hints(None, \"private\"); config where cache_ttl is parsed out (e.g. env var missing yields None) but cache_scope is set.","commonSituations":"Setting cache_scope from a config file while forgetting cache_ttl; typo like cache_ttl=\"0\" string coercion failing upstream and arriving as None; migrating from an older FastMCP version where scope behaved differently.","solutions":["Provide a positive integer cache_ttl in seconds alongside cache_scope, e.g. FastMCP(cache_ttl=300, cache_scope=\"public\").","If caching is not wanted, remove cache_scope as well — pass neither.","Validate your config loading so cache_ttl defaults to an integer, not None, when scope is configured.","Catch ValueError at server-construction time and fail fast with a clear config error."],"exampleFix":"// before\nmcp = FastMCP(\"server\", cache_scope=\"public\")  # ValueError\n// after\nmcp = FastMCP(\"server\", cache_ttl=300, cache_scope=\"public\")","handlingStrategy":"validation","validationCode":"def check_cache_config(ttl: int | None, scope: str | None) -> None:\n    if scope is not None and ttl is None:\n        raise ValueError(\"cache_scope requires cache_ttl\")\n    if ttl is not None and ttl <= 0:\n        raise ValueError(\"cache_ttl must be positive\")","typeGuard":"def has_valid_cache_hint(ttl: int | None, scope: str | None) -> bool:\n    return scope is None or (isinstance(ttl, int) and ttl > 0)","tryCatchPattern":"try:\n    mcp = FastMCP(\"server\", cache_ttl=cfg.ttl, cache_scope=cfg.scope)\nexcept ValueError as e:\n    raise ConfigError(f\"invalid cache settings: {e}\") from e","preventionTips":["Always pair cache_scope with a positive integer cache_ttl","Validate config parsing so a missing TTL env var doesn't become None while scope survives","Fail fast at startup — this error fires at server construction, before any request"],"tags":["config","caching","validation","fastmcp"],"backgroundTag":"invalid-configuration","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}