{"record":{"id":"30ffc03431a82ed9","repo":"tinyhumansai/openhuman","slug":"composio-cache-catalog-fetch-failed-serving-sta","errorCode":null,"errorMessage":"[composio-cache] catalog fetch failed; serving stale cache:","messagePattern":"\\[composio-cache\\] catalog fetch failed; serving stale cache:","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/src/lib/composio/catalogCache.ts","lineNumber":121,"sourceCode":"  const fetchPromise = listToolkits(options)\n    .then(response => {\n      // Only cache the response if no invalidation happened while it was in\n      // flight; otherwise it belongs to a stale tenant. Still return it to\n      // this caller — just don't poison the shared cache for future reads.\n      if (generation === startGeneration) {\n        writePersisted(response);\n      } else {\n        console.debug('[composio-cache] discarding catalog response invalidated mid-flight');\n      }\n      return response;\n    })\n    .catch(err => {\n      // On failure, fall back to a stale cache if we have one rather than\n      // forcing the UI into an error state for a list that rarely changes.\n      // Skip the fallback if we were invalidated mid-flight — the cached\n      // value belongs to the previous tenant.\n      if (cached && generation === startGeneration) {\n        console.warn(\n          '[composio-cache] catalog fetch failed; serving stale cache:',\n          err instanceof Error ? err.message : String(err)\n        );\n        return cached.response;\n      }\n      throw err;\n    })\n    .finally(() => {\n      // Only clear the slot if it's still ours — an invalidation may have\n      // reset `inflight` to null and a newer fetch taken its place.\n      if (inflight === fetchPromise) {\n        inflight = null;\n      }\n    });\n  inflight = fetchPromise;\n  return fetchPromise;\n}\n","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/app/src/lib/composio/catalogCache.ts#L103-L139","documentation":"Fetching the Composio toolkit catalog failed and the cache served its last persisted copy instead: listToolkits rejected, so the caller receives the stale (possibly outdated) catalog rather than failing. The generation guard already ensured an invalidated mid-flight response would not poison the cache; this is the deliberate availability-over-freshness fallback when Composio/the network is unreachable.","triggerScenarios":"Thrown at app/src/lib/composio/catalogCache.ts:121 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Treat the stale catalog as temporary — the next successful fetch refreshes the persisted cache","Check the warned error for network vs auth failure (expired Composio key rejects listToolkits)","Verify Composio connectivity/credentials in connections settings if staleness persists","The UI continues to work; toolkit lists may just lack newest additions"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}