Fix the HTLC failure reason reported when a peer is offline
What changed, and why it matters
This commit fixes a small but meaningful error-code bug in the Lightning Dev Kit. When a payment is being routed through a node whose peer just went offline (but the network gossip hasn't yet marked the channel as disabled), the node was incorrectly reporting 'channel not ready' instead of 'peer offline'. The fix makes the reported failure reason accurate, which helps other nodes and payment senders understand why a route failed and choose better routes.
Treat as a routine correctness/security-hardening patch. Reviewers should verify that no other failure paths conflate disconnection, disabled channels, and not-ready channels, and consider whether any tests cover the newly distinguished PeerOffline case.
Security signals we found
Incorrect error reporting could mislead routing/payment logic
Fixes a logic branch in HTLC failure handling
Documentation updated to clarify security-relevant failure semantics
Evidence from the diff
In channelmanager.rs, the HTLC forwarding failure path now checks whether the channel counterparty is disconnected before falling back to ChannelNotReady. If the peer is offline but the channel is still enabled in gossip, it returns LocalHTLCFailureReason::PeerOffline. The ChannelDisabled doc comment in onion_utils.rs is also updated to clarify that it applies when the counterparty has been offline for some time, distinguishing it from the newly handled PeerOffline case.
Changed components
lightning/src/ln/channelmanager.rslightning/src/ln/onion_utils.rsInspect captured patch +4 / −1
diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs
index 04f25bc..33be6cb 100644
--- a/lightning/src/ln/channelmanager.rs
+++ b/lightning/src/ln/channelmanager.rs
@@ -4807,6 +4807,8 @@ where
if !chan.context.is_live() {
if !chan.context.is_enabled() {
return Err(LocalHTLCFailureReason::ChannelDisabled);
+ } else if !chan.context.is_connected() {
+ return Err(LocalHTLCFailureReason::PeerOffline);
} else {
return Err(LocalHTLCFailureReason::ChannelNotReady);
}
diff --git a/lightning/src/ln/onion_utils.rs b/lightning/src/ln/onion_utils.rs
index eab5e72..7cf1062 100644
--- a/lightning/src/ln/onion_utils.rs
+++ b/lightning/src/ln/onion_utils.rs
@@ -1573,7 +1573,8 @@ pub enum LocalHTLCFailureReason {
///
/// The forwarding node has tampered with this value, or has a bug in its implementation.
FinalIncorrectHTLCAmount,
- /// The channel has been marked as disabled because the channel peer is offline.
+ /// The HTLC couldn't be forwarded because the channel counterparty has been offline for some
+ /// time.
ChannelDisabled,
/// The HTLC expires too far in the future, so it is rejected to avoid the worst-case outcome
/// of funds being held for extended periods of time.
Why this scored 33/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.