{"record":{"id":"924bf2f3b9852dcc","repo":"apache/cassandra","slug":"readtimeoutexception-924bf2","errorCode":null,"errorMessage":"ReadTimeoutException","messagePattern":"ReadTimeoutException","errorType":"exception","errorClass":"ReadTimeoutException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/service/reads/repair/BlockingReadRepair.java","lineNumber":192,"sourceCode":"            if (!repair.awaitRepairsUntil(deadline, NANOSECONDS))\n            {\n                timedOut = repair;\n                break;\n            }\n            repairPlan = repair.repairPlan();\n        }\n        if (timedOut != null)\n        {\n            // We got all responses, but timed out while repairing;\n            // pick one of the repairs to throw, as this is better than completely manufacturing the error message\n            int blockFor = timedOut.blockFor();\n            int received = Math.min(blockFor - timedOut.waitingOn(), blockFor - 1);\n            if (Tracing.isTracing())\n                Tracing.trace(\"Timed out while read-repairing after receiving all {} data and digest responses\", blockFor);\n            else\n                logger.debug(\"Timeout while read-repairing after receiving all {} data and digest responses\", blockFor);\n\n            throw new ReadTimeoutException(replicaPlan().consistencyLevel(), received, blockFor, true);\n        }\n\n        if (repairs.isEmpty() || repairPlan.stillAppliesTo(ClusterMetadata.current()))\n            return;\n    }\n\n    @Override\n    public void repairPartition(DecoratedKey dk, Map<Replica, Mutation> mutations, ReplicaPlan.ForWrite writePlan, ReadRepairSource rrSource)\n    {\n        // non-Accord reads only ever touch one table and key so all mutations need to be applied either transactionally\n        // or non-transactionally (not a mix). There is no retry loop here because read repair is relatively rare so it racing\n        // with changes to migrating ranges should also be pretty rare so it isn't worth the added complexity. If you were\n        // to add a retry loop you would need to be careful to correctly set/unset allowPotentialTransactionConflicts in the mutations\n        // since that is set if it is routed to Accord\n        //\n        // If this is an Accord transaction that is in interoperability mode and executing a read repair\n        // then we take the non-transactional path and the mutations are intercepted in ReadCoordinator.sendRepairMutation\n        // which will ensure the repair mutation runs in the command store thread after preceding transactions are done","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/service/reads/repair/BlockingReadRepair.java#L174-L210","documentation":"BlockingReadRepair.awaitWrites throws ReadTimeoutException when the read-repair write phase triggered by a digest mismatch does not complete in time. It reports that all data/digest responses arrived but the repair writes timed out, surfaced with received = min(blockFor - waitingOn, blockFor - 1) so the client sees a read timeout attributed to the repair.","triggerScenarios":"A read with CL requiring multiple replicas finds a digest mismatch; the blocking repair writes mutations to out-of-date replicas and awaits their acknowledgments; those writes hit the write timeout (slow replica, overload, tombstone-heavy repair).","commonSituations":"Replicas out of sync for a long time (a node down then returning) so repairs move a lot of data; TombstoneOverwhelming during repair writes; disk contention making the repair writes exceed write_request_timeout.","solutions":["Increase write_request_timeout_in_ms / read_request_timeout_in_ms if repairs legitimately need longer","Run nodetool repair to bring replicas back in sync so reads stop triggering large blocking repairs","Check replica health (compactions backlog, dropped messages, GC pauses) that makes repair writes slow","Reduce inconsistency window: fix hinted-handoff backlogs and monitor digest-mismatch rates"],"exampleFix":"// before\ncassandra.yaml: write_request_timeout_in_ms: 2000\n// after\ncassandra.yaml: write_request_timeout_in_ms: 5000","handlingStrategy":"retry","validationCode":"// Before reads: check replica sync state\n// shell: nodetool repair -pr (scheduled) and monitor 'Read repair' metrics; skip strict-CL reads if repair backlog is large","typeGuard":null,"tryCatchPattern":"try {\n  return session.execute(query);\n} catch (e) {\n  if (e instanceof ReadTimeoutException) {\n    // repair writes timed out; retry after backoff, then escalate to nodetool repair\n    return retryWithBackoff(query, 2).catch(() => scheduleRepair(keyspace, table));\n  }\n  throw e;\n}","preventionTips":["Schedule regular nodetool repair so blocking repairs stay small","Raise write_request_timeout_in_ms if repairs are data-heavy","Monitor TombstoneOverwhelming and dropped mutations that stall repair writes","Keep hint backlogs drained to limit replica divergence"],"tags":["read-repair","read-timeout","consistency","timeout"],"backgroundTag":"request-timeout","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}