{"record":{"id":"1586e93c9c2e1f7b","repo":"tursodatabase/turso","slug":"getallrows-exceeded-max-io-retries-io-retries","errorCode":null,"errorMessage":"getAllRows: exceeded ${MAX_IO_RETRIES} IO retries","messagePattern":"getAllRows: exceeded (.+?) IO retries","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"bindings/react-native/src/Statement.ts","lineNumber":319,"sourceCode":"          rows = rows.concat(bulk.rows);\n        }\n\n        if (bulk.status === TursoStatus.DONE) {\n          return rows;\n        }\n\n        if (bulk.status === TursoStatus.IO) {\n          this._statement.runIo();\n          if (this._extraIo) {\n            await this._extraIo();\n          }\n          continue;\n        }\n\n        throw new Error(`getAllRows failed with status: ${bulk.status}`);\n      }\n\n      throw new Error(`getAllRows: exceeded ${MAX_IO_RETRIES} IO retries`);\n    } finally {\n      this._statement.reset();\n      if (this._execLock) {\n        this._execLock.release();\n      }\n    }\n  }\n\n  /**\n   * Read current row into an object\n   *\n   * @returns Row object with column name keys\n   */\n  private readRow(): Row {\n    const row: Row = {};\n    const columnCount = this._statement.columnCount();\n\n    for (let i = 0; i < columnCount; i++) {","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/bindings/react-native/src/Statement.ts#L301-L337","documentation":"Statement.all()'s bulk-read loop aborts after MAX_IO_RETRIES iterations, which is 1,000,000 (Statement.ts:296). Each iteration that returns TursoStatus.IO calls runIo() and awaits the optional _extraIo() drain, so reaching the cap means the engine kept requesting IO a million times without the read completing — IO that makes no forward progress, effectively an infinite-loop safeguard rather than a legitimate large workload.","triggerScenarios":"A partial-sync database where every bulk read returns IO and the IO drain never satisfies the request: _extraIo not wired or its fetches returning empty/unusable bodies without throwing; a sync endpoint that accepts requests but never delivers the needed pages; an offline device whose fetches fail silently inside the configured IO processor.","commonSituations":"Long-lived mobile sessions on flaky networks where the sync engine re-requests the same missing page forever; misconfigured sync URL or auth token causing the server to respond without the requested data; developing against a local sync server that returns 404 bodies that never error.","solutions":["Verify the sync URL and auth token are correct and the server actually returns the requested pages (inspect the ioProcessor logs)","Ensure setFileSystemImpl() and the sync IO processor are configured before running queries against a partial-sync database","Check network connectivity before issuing large all() reads and surface offline state in the UI instead of looping","If connectivity is healthy and it still reproduces, capture the HTTP traffic and report it — a healthy drain should complete in a handful of IO cycles"],"exampleFix":"// before\nconst rows = await stmt.all(); // hangs effectively forever, then: exceeded 1000000 IO retries\n\n// after\nimport NetInfo from '@react-native-community/netinfo';\nconst net = await NetInfo.fetch();\nif (!net.isConnected) throw new Error('offline — cannot complete partial-sync read');\nconst rows = await stmt.all();","handlingStrategy":"retry","validationCode":"import NetInfo from '@react-native-community/netinfo';\n\nasync function canReachSyncServer(): Promise<boolean> {\n  const net = await NetInfo.fetch();\n  return net.isConnected === true && net.isInternetReachable === true;\n}\n// gate large partial-sync reads:\nif (!(await canReachSyncServer())) throw new Error('offline');","typeGuard":"function isIoRetryLimit(e: unknown): boolean {\n  return e instanceof Error && e.message.includes('exceeded') && e.message.includes('IO retries');\n}","tryCatchPattern":"try {\n  return await stmt.all();\n} catch (e) {\n  if (isIoRetryLimit(e)) {\n    // IO made no progress — verify connectivity/config, then retry once later\n    await waitOnline();\n    return stmt.all();\n  }\n  throw e;\n}","preventionTips":["Surface connectivity state before triggering reads on partial-sync databases","Verify sync URL/auth by running a tiny single-row get() before big all() scans","Watch the '[Turso HTTP]' console logs — endless page requests with no error point to a server/config issue","A healthy IO drain finishes in a handful of cycles; treat long-running reads as a red flag in dev builds"],"tags":["partial-sync","infinite-loop","io","react-native","network"],"backgroundTag":"retry-limit-exceeded","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}