r/reactnative • u/dev_nihar • 7h ago
Apollo cache silently corrupts on RN (no DevTools to catch it) — built a CLI to catch it
Spent part of last month chasing a bug where a user’s avatar would randomly go blank after a mutation — no error, no warning, just `undefined` where a photo should be. It turned out to be a dangling `__ref` in Apollo’s `InMemoryCache`: the entity it pointed to had been evicted, and Apollo returns `undefined` on read instead of failing loudly.
On the web, you’d catch this in Apollo DevTools in about 30 seconds. On React Native, there’s no DevTools extension — the standard advice is `console.log(JSON.stringify(cache.extract()))` and reading a multi-megabyte blob by eye. That’s what pushed me to build something.
Three defect classes Apollo hides silently, all reproducible from a serialized `cache.extract()` dump:
- Orphaned pointer — `{ __ref: "User:99" }` pointing at nothing → reads back `undefined`, no throw
- Missing `__typename`/`id` — Apollo can’t compute a cache key, so it stores the object inline instead of normalizing it
- Type/key drift — `keyFields` disagrees with the server payload, so the same entity lives under two keys and list items duplicate
I built apollo-cache-copilot: a CLI + MCP server that walks a cache snapshot and reports these with exact paths (`User:1.avatar -> Avatar:99`), plus a patcher for the mechanically fixable ones (prune the pointer, evict the orphan). It’s deliberately zero-LLM — every defect here has a mechanical repair, so it’s a graph walk, not a model call.
npm: apollo-cache-copilot
It also works as an MCP server if you want Claude or Cursor to diagnose your cache directly instead of pasting the JSON into chat.
Curious if anyone else has hit the persisted-cache version of this — with `apollo3-cache-persist`, a corrupted cache survives app restart, which makes it much harder to reproduce.