{"record":{"id":"a2d13becd0d9b7e5","repo":"apache/superset","slug":"cached-data-not-found","errorCode":null,"errorMessage":"Cached data not found","messagePattern":"Cached data not found","errorType":"exception","errorClass":"ChartDataCacheLoadError","httpStatus":404,"severity":"error","filePath":"superset/charts/data/query_context_cache_loader.py","lineNumber":28,"sourceCode":"#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\nfrom typing import Any\n\nfrom superset import cache\nfrom superset.commands.chart.exceptions import ChartDataCacheLoadError\n\n\nclass QueryContextCacheLoader:  # pylint: disable=too-few-public-methods\n    @staticmethod\n    def load(cache_key: str) -> dict[str, Any]:\n        cache_value = cache.get(cache_key)\n        if not cache_value:\n            raise ChartDataCacheLoadError(\"Cached data not found\")\n\n        return cache_value[\"data\"]\n","sourceCodeStart":10,"sourceCodeEnd":31,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/charts/data/query_context_cache_loader.py#L10-L31","documentation":"QueryContextCacheLoader.load() raises ChartDataCacheLoadError(\"Cached data not found\") when superset's shared cache returns a falsy value for the given cache_key. This loader is the retrieval half of the chart-data 'cache as payload' flow (used by async queries and force_cached requests), where an entire QueryContext payload is stored under one key. A miss means the key expired, was evicted, the cache backend was flushed/restarted, or the key was computed against a different cache config.","triggerScenarios":"Calling ChartDataAsyncQueryRestApi result retrieval after the cached entry TTL expired; GET /api/v1/chart/data/<cache_key> style flows where the cache key was generated by a different worker with different CACHE_CONFIG or a different Superset version (key hashing changed); Redis/memcached restart or FLUSHDB between query submission and result pickup; force_cached=True with an expired key.","commonSituations":"Multi-worker or multi-node deployments where nodes disagree on cache key generation; CACHE_CONFIG TTL shorter than long-running queries; upgrading Superset versions that change query context serialization, invalidating old keys; local dev with in-memory cache restarted between submit and fetch.","solutions":["Re-run the query without force_cached so a fresh payload is computed and re-cached.","Raise or remove the TTL/eviction limits on the cache backend used by ChartDataAsyncQueryRestApi (CACHE_CONFIG / FEATURE_FLAG async queries) so results survive until fetched.","Ensure all nodes share the same cache backend (Redis) and the same Superset version so cache keys hash identically.","Check for cache flushes or Redis maxmemory evictions (INFO stats: evicted_keys) if misses are frequent."],"exampleFix":"# before\nfrom superset.charts.data.query_context_cache_loader import QueryContextCacheLoader\ndata = QueryContextCacheLoader.load(cache_key)\n\n# after\nfrom superset.commands.chart.exceptions import ChartDataCacheLoadError\nfrom superset.charts.data.query_context_cache_loader import QueryContextCacheLoader\n\ntry:\n    data = QueryContextCacheLoader.load(cache_key)\nexcept ChartDataCacheLoadError:\n    data = reexecute_query_and_cache()  # fall back to a fresh run","handlingStrategy":"fallback","validationCode":"from superset import cache\n\ndef cache_entry_exists(cache_key: str) -> bool:\n    return bool(cache.get(cache_key))","typeGuard":null,"tryCatchPattern":"from superset.commands.chart.exceptions import ChartDataCacheLoadError\nfrom superset.charts.data.query_context_cache_loader import QueryContextCacheLoader\n\ntry:\n    data = QueryContextCacheLoader.load(cache_key)\nexcept ChartDataCacheLoadError:\n    data = reexecute_query_and_store(cache_key)","preventionTips":["Set the chart-data cache TTL longer than the maximum expected time between query submission and result pickup.","Use a shared, durable Redis cache for async queries across all workers/replicas.","Keep Superset versions uniform across nodes so cache keys are computed identically."],"tags":["cache","chart-data","async","redis"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}