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

  1. 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.
  2. Use one target_id per distinct MCP server; reuse it across all clients sharing the store.
  3. If you don't need cross-client sharing, drop the custom store and use the default in-memory store (CacheConfig() or cache=True).
  4. 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

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


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