{"record":{"id":"4a93e840d7bf26c5","repo":"TanStack/query","slug":"provided-storage-does-not-implement-entries-meth","errorCode":null,"errorMessage":"Provided storage does not implement `entries` method. Garbage collection is not possible without ability to iterate over storage items.","messagePattern":"Provided storage does not implement `entries` method\\. Garbage collection is not possible without ability to iterate over storage items\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/query-persist-client-core/src/createPersister.ts","lineNumber":267,"sourceCode":"    if (storage?.entries) {\n      const storageKeyPrefix = `${prefix}-`\n      const entries = await storage.entries()\n      for (const [key, value] of entries) {\n        if (key.startsWith(storageKeyPrefix)) {\n          let persistedQuery: PersistedQuery\n          try {\n            persistedQuery = await deserialize(value)\n          } catch {\n            await storage.removeItem(key)\n            continue\n          }\n          if (isExpiredOrBusted(persistedQuery)) {\n            await storage.removeItem(key)\n          }\n        }\n      }\n    } else if (process.env.NODE_ENV === 'development') {\n      throw new Error(\n        'Provided storage does not implement `entries` method. Garbage collection is not possible without ability to iterate over storage items.',\n      )\n    }\n  }\n\n  async function restoreQueries(\n    queryClient: QueryClient,\n    filters: Pick<QueryFilters, 'queryKey' | 'exact'> = {},\n  ): Promise<void> {\n    const { exact, queryKey } = filters\n\n    if (storage?.entries) {\n      const storageKeyPrefix = `${prefix}-`\n      const entries = await storage.entries()\n      for (const [key, value] of entries) {\n        if (key.startsWith(storageKeyPrefix)) {\n          let persistedQuery: PersistedQuery\n          try {","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/TanStack/query/blob/159982c80b844487054155c38ffc760fe4208daf/packages/query-persist-client-core/src/createPersister.ts#L249-L285","documentation":"Dev-only error from `persisterGc` in `createPersister` (`@tanstack/query-persist-client-core`). Garbage collection iterates every storage entry to find expired items; if the supplied `storage` lacks an `entries()` method this is impossible, so in development the persister fails loudly. In production it silently skips GC.","triggerScenarios":"Passing a minimal storage shim (only `getItem`/`setItem`/`removeItem`) to `createPersister({ storage })`; using `localStorage`-like polyfills that omit `entries`; providing a custom AsyncStorage that did not implement iteration; calling `persisterGc()` directly in a dev build with such a storage.","commonSituations":"React Native `AsyncStorage` (no `entries`); an in-memory Map wrapper without exposing `entries`; older `localforage` versions; partial storage adapters written for a different interface.","solutions":["Implement `entries()` on your storage adapter, returning an iterable of `[key, value]` pairs (async iterator or array).","Use a storage that already supports it, e.g. a `Map` or a fully-featured `localforage` instance.","Wrap the storage: `const fullStorage = { ...storage, entries: async () => { ... } }`.","If iteration is genuinely impossible, suppress GC by only calling `persisterGc` in environments where the storage supports it (the error is dev-only, so production will no-op)."],"exampleFix":"// before\nconst persister = createPersister({ storage: window.localStorage, ... })\n// after\nconst storage = {\n  ...window.localStorage,\n  entries: async () => Object.entries(window.localStorage).map(([k, v]) => [k, v]),\n}\nconst persister = createPersister({ storage, ... })","handlingStrategy":"validation","validationCode":"function assertStorageIterable(storage: any) {\n  if (!storage || typeof storage.entries !== 'function') {\n    throw new Error('persisterGc requires storage.entries()')\n  }\n}","typeGuard":"const hasEntries = (s: any): s is { entries(): Promise<Iterable<[string, any]>> } =>\n  !!s && typeof s.entries === 'function'","tryCatchPattern":"try { await persister.persisterGc() } catch (e) { if (/entries method/.test((e as Error).message)) console.warn('GC skipped:', e.message) }","preventionTips":["Choose a storage adapter that implements `entries()` (Map, localforage).","Document the full storage interface required by createPersister.","In production, accept the silent skip if iteration is unavailable.","Add an adapter test asserting `entries()` exists before using GC."],"tags":["persister","storage","garbage-collection","validation","dev-only"],"backgroundTag":null,"analyzedSha":"159982c80b844487054155c38ffc760fe4208daf","analyzedAt":"2026-08-12T16:21:52.822Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}