PrefectHQ/fastmcp · error · ValueError
a custom cache store requires CacheConfig.target_id for Fast
Error message
a custom cache store requires CacheConfig.target_id for FastMCP transports: the server URL the SDK derives an identity from is not available here, so entries in a shared store could never be served to another client
What it means
The SEP-2549 response cache partitions a shared store by a target_id derived from the server URL — but FastMCP transports abstract that URL away, so the SDK cannot derive it. If you supply CacheConfig(store=...) without an explicit target_id, entries could never be correctly attributed across clients, so Client.__init__/_build_response_cache raises ValueError rather than silently mis-partitioning the shared store.
Source
Thrown at fastmcp_slim/fastmcp/client/client.py:611
Response caching is opt-in: `None` (the default) and `False` both leave it
disabled, so a legacy connection is byte-identical to pre-v4 behavior (no
message-handler wrapping, no caching). `True` enables it with the default
`CacheConfig` (honoring server `ttlMs`/`cacheScope` hints via a per-client
in-memory store); a `CacheConfig` customizes it.
Our transports abstract away the server URL the SDK Client uses to derive a
cache identity, so `target_id` comes from the explicit `CacheConfig.target_id`
or a random per-client id — meaning a custom shared store cannot serve one
client's entries to another (documented on the parameter).
"""
if cache is None or cache is False:
return None
config = cache if isinstance(cache, CacheConfig) else CacheConfig()
target_id = config.target_id
if target_id is None:
if config.store is not None:
raise ValueError(
"a custom cache store requires CacheConfig.target_id for FastMCP "
"transports: the server URL the SDK derives an identity from is not "
"available here, so entries in a shared store could never be served "
"to another client"
)
target_id = uuid.uuid4().hex
return ClientResponseCache(
store=config.store
if config.store is not None
else InMemoryResponseCacheStore(),
partition=config.partition,
arm_id=hashlib.sha256(target_id.encode()).hexdigest(),
default_ttl_ms=config.default_ttl_ms,
clock=config.clock,
share_public=config.share_public,
# Lazy: the negotiated version is unknown until the handshake completes.
negotiated_version=lambda: (View on GitHub (pinned to 1f02114297)
Solutions
- Set CacheConfig.target_id to a stable identifier for the server (e.g. the MCP server URL or a slug) so the shared store partitions correctly.
- Use one target_id per distinct MCP server; reuse it across all clients sharing the store.
- If you don't need cross-client sharing, drop the custom store and use the default in-memory store (CacheConfig() or cache=True).
- Use cache=False to disable caching if a store isn't required.
Example fix
// before: shared store without identity client = Client(url, cache=CacheConfig(store=redis_store)) // after: explicit partition id for the shared store client = Client(url, cache=CacheConfig(store=redis_store, target_id='https://mcp.example.com/mcp'))
Defensive patterns
Strategy: validation
Validate before calling
from fastmcp.client.client import CacheConfig
cfg = CacheConfig(store=redis_store)
if cfg.store is not None and cfg.target_id is None:
raise ValueError('Custom cache store requires an explicit target_id') Type guard
def cache_config_is_valid(cfg: CacheConfig) -> bool:
return not (cfg.store is not None and cfg.target_id is None) Try / catch
try:
client = Client(url, cache=CacheConfig(store=redis_store))
except ValueError as e:
if 'custom cache store requires' in str(e):
client = Client(url, cache=CacheConfig(store=redis_store, target_id=server_identity))
else:
raise Prevention
- Always pair a custom cache store with a stable CacheConfig.target_id (e.g. the server URL).
- Use one target_id per MCP server so shared-store partitions stay correct.
- If you don't need cross-client sharing, omit the store and use the default in-memory cache.
- Validate CacheConfig at config-load time, not at Client construction time.
When it happens
Trigger: Client(url, cache=CacheConfig(store=my_shared_store)) — a CacheConfig with a custom store but target_id=None, on any FastMCP transport. (CacheConfig() without a store is fine: it gets a random per-client id.)
Common situations: Teams sharing a Redis/disk cache store across many clients for rate-limit or latency reasons; copying a CacheConfig example and adding a store but not target_id.
Understand the failure class
Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.
Related errors
- mode must be 'legacy', 'auto', or one of {list(MODERN_PROTOC
- The 'verify' parameter is only supported for HTTP transports
- ClientGroup requires at least one client
- Protocol mode for server {name!r} must be a string
- Missing required arguments: {missing}
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/f4952e784f208108.
Report an issue: GitHub.