CorruptDurableStateException
Thrown during a node's start-up restore when the RaftStorage it was given returns durable state that violates the storage contract: a persisted term outside the plausible range (issue #1855), a snapshot position or log that no real node could have stored (#1887), a restored log entry whose config names no voters, or a restored snapshot config naming no voters on a node whose bootstrap is the learner seed and so has nothing to fall back to (#2676). The term case is the one argued below.
Why this is loud rather than repaired
Terms advance once per election, so an honest deployment stays many orders of magnitude below the 2^60 ceiling the wire boundary already enforces (issue #1833). A restored term above it — or below zero — is therefore not a value to interpret; it is evidence that the durable state is wrong.
Clamping it would be worse than the fault: rewriting a persisted term silently discards the record of which terms this node has already voted in, so it can vote a second time in a term it has forgotten — a Raft §5.2 election-safety violation, and a strictly worse trade than the lost liveness.
Ignoring it is not free either. The node adopts the poisoned term, every frame it emits is dropped by peers as implausible, and every frame it receives looks stale — it is permanently and silently isolated. In a one-voter bootstrap it is worse still: the node wins its own election, currentTerm + 1 wraps, and it persists a negative term, driving its own durable state backwards past RaftStorage.term's monotonicity guarantee.
What to do about it
This exception is a report about the medium, whichever adapter is reading it. kuilt's own durable adapter is DurableStoreRaftStorage; any other persistent one is consumer code — and the report means the same thing either way, because that adapter round-trips faithfully and validates no ranges, so a damaged record reaches this check rather than being repaired behind it. Treat it as you would a failed integrity check: inspect the persisted term (a truncated column, a sign-extended Int, a torn or partially deserialised read are the usual causes) and repair or re-provision the node deliberately. Erasing the node's durable state and letting it rejoin as a fresh member is safe; silently continuing is not — and with DurableStoreRaftStorage "erasing" is concrete, because its three DurableStoreRaftStorage.META_KEY-family constants name exactly what to delete.
Note that DurableStoreRaftStorage.open raises this same type for a record it cannot decode, or one carrying a storage format version it does not know. Those messages name the us.tractat.kuilt.store.StoreKey involved; this one names the value.
Because the restore runs in the coroutine started by CoroutineScope.raftNode, this surfaces through the scope rather than from the raftNode(...) call itself.