{"record":{"id":"69ea3a3e15128375","repo":"PrefectHQ/fastmcp","slug":"cimd-server-returned-304-not-modified-without-cach","errorCode":null,"errorMessage":"CIMD server returned 304 Not Modified without cached document","messagePattern":"CIMD server returned 304 Not Modified without cached document","errorType":"exception","errorClass":"CIMDFetchError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/server/auth/cimd.py","lineNumber":369,"sourceCode":"\n        try:\n            response = await ssrf_safe_fetch_response(\n                client_id_url,\n                require_path=True,\n                max_size=self.MAX_RESPONSE_SIZE,\n                timeout=self.timeout,\n                overall_timeout=30.0,\n                request_headers=request_headers,\n                allowed_status_codes=allowed_status_codes,\n            )\n        except SSRFError as e:\n            raise CIMDValidationError(str(e)) from e\n        except SSRFFetchError as e:\n            raise CIMDFetchError(str(e)) from e\n\n        if response.status_code == 304:\n            if cached is None:\n                raise CIMDFetchError(\n                    \"CIMD server returned 304 Not Modified without cached document\"\n                )\n\n            now = time.time()\n            if self._has_freshness_headers(response.headers):\n                policy = self._parse_cache_policy(response.headers, now)\n            else:\n                # RFC allows 304 to omit unchanged headers. Preserve existing\n                # cache policy rather than resetting to fallback defaults.\n                policy = _CIMDCachePolicy(\n                    etag=None,\n                    last_modified=None,\n                    expires_at=now + cached.freshness_lifetime,\n                    freshness_lifetime=cached.freshness_lifetime,\n                    no_store=False,\n                    must_revalidate=cached.must_revalidate,\n                )\n","sourceCodeStart":351,"sourceCodeEnd":387,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/server/auth/cimd.py#L351-L387","documentation":"CIMDFetcher implements HTTP conditional requests: on a revalidation fetch the server may answer 304 Not Modified, and fetch() then reuses the cached document. This error is raised when a 304 arrives but there is no cached entry to fall back on — an inconsistent protocol state, since 304 only makes sense as a reply to a conditional request backed by a cached copy.","triggerScenarios":"fetch() called with conditional headers (If-None-Match/If-Modified-Since) built from cache metadata while the internal cache entry for that client_id_url is missing or was evicted (MAX_CACHE_SIZE eviction, manual removal, or cache cleared between calls).","commonSituations":"Long-running servers where the 1000-entry LRU-ish process cache evicted the entry but external state still sends conditional headers; restart of a forked worker process losing in-memory cache; custom callers passing conditional request headers directly to fetch().","solutions":["Clear the stale conditional state and re-fetch the document unconditionally (drop If-None-Match/If-Modified-Since headers)","If you call fetch() directly with conditional headers, ensure a cache entry exists for that client_id_url first","Restart the affected flow: call fetch/get_client without cache hints so a full 200 response is retrieved and re-cached","Report if this occurs through get_client alone — it indicates an internal cache-eviction race"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    doc = await fetcher.fetch(url, conditional_headers=headers)\nexcept CIMDFetchError as e:\n    if \"304\" in str(e):\n        doc = await fetcher.fetch(url)  # unconditional re-fetch\n    else:\n        raise","preventionTips":["Don't pass conditional headers to fetch() unless you populated the cache yourself","Avoid relying on long-lived external references to in-memory cache entries","Let CIMDFetcher manage its own cache lifecycle"],"tags":["oauth","cimd","http-cache","caching"],"backgroundTag":"http-304-without-cache","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}