You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
ChannelManager read errors start a fresh node #1026
ldk-node treats any ChannelManager KV-store read error as a missing manager and creates a fresh, empty node. A timeout, connection failure, authentication error, or exhausted VSS 5xx can therefore return a successful node instead of BuildError::ReadFailed.
ifletOk(reader) = channel_manager_bytes_res {// Restore ChannelManager.}else{// Create a fresh ChannelManager.}
The else branch does not distinguish NotFound from other storage failures.
Impact
An established node can start with zero channels after a manager read failure. If the fresh manager is later persisted, it can overwrite the valid manager and permanently destroy the live off-chain channel state.
Loaded ChannelMonitors remain active, so the expected manager-only outcome is unilateral channel closure, fees, and delayed access to funds—not loss of the full channel balance. Principal loss requires the monitors to also be missing or unsafe.
Verification
The vulnerable behavior is confirmed by source inspection of upstream main.
The attached test poc.txt is an end-to-end regtest PoC using two real ldk-node instances and a real channel. It injects a manager-only ErrorKind::Other at the KVStore boundary and verifies that:
a total store outage fails closed;
a manager-only failure builds a node with zero channels;
the channel is unilaterally closed on-chain; and
graceful shutdown overwrites the valid manager with the smaller empty manager.
ErrorKind::Other is the error class produced by VSS for a 5xx after retry exhaustion. The PoC tests the resulting KV-store failure directly; it does not emulate the HTTP request or VSS retry layer itself.
Proposed fix
match channel_manager_bytes_res {Ok(reader) => restore_manager(reader)?,Err(error)if error.kind() == std::io::ErrorKind::NotFound => create_fresh_manager(),Err(error) => {log_error!(logger,"Failed to read ChannelManager: {}", error);returnErr(BuildError::ReadFailed);}}
Additionally, a missing manager with existing monitors should require an explicit recovery path rather than appearing as a normal empty node.
Activity
tnull commentedon Aug 7, 2026
Thanks for reporting, fixed in #1032.
Fail closed on manager read errors
Fail closed on manager read errors