Skip to content

bug: send shows connecting to network until lightning connections is opened #1389

Description

@ovitrif

Refs:

What happened?

Seen once, on 25 Sep 2026, on an Android emulator (API 36.1) running Bitkit dev 2.5.0 (190) on regtest, during a demo walkthrough: paying a contact showed "Connecting to network" for about 25 s, then an amount screen that offered only Savings. After Continue, the confirm screen stayed on "Connecting to network" for over 3 minutes. After opening Settings › Advanced › Lightning Connections once and starting Pay again, the amount screen offered Spending with the switch.

I read that as a channel that was usable all along and a stale cached state. That is an inference from the second try; I did not check the node's channel state during the stuck send.

The rest of this section is a reading of the code on master (4d13a1d), not a reproduction:

  • ui/sheets/SendSheet.kt:102-107 covers the Send flow with the sync overlay while the node has channels and none is usable in lightningState:
    hasAnyChannels && lightningState.channels.none { it.isUsable }
    The condition is at :105-106; the overlay is drawn at :576-586.
  • lightningState.channels is a snapshot that only LightningRepo.syncState() refreshes (LightningRepo.kt:1668-1678): at node start (:418), after connectToTrustedPeers() (:1226), after a successful sync() (:756-758), on ChannelPending or ChannelReady (:803-806), and after payments and channel opens or closes.
  • A channel that becomes usable again when its peer reconnects produces no LDK event. AppViewModel.handleLdkEvent() (AppViewModel.kt:1347-1391, the when at :1364-1385) handles every node event, and none marks a reconnect; ChannelReady fires once per channel. The background sync's SyncCompleted runs WalletRepo.debounceSyncByEvent() (WalletRepo.kt:302-310), which refreshes balances, transfers and activities but not the channel list.
  • The wait does not re-read either: LightningRepo.waitForUsableChannels() (:1382-1421) re-reads channels only when the list is empty (:1396-1400). Otherwise it waits for a state change that nothing emits, up to CHANNELS_USABLE_TIMEOUT (:2186, 15 s), and the callers then check canSend() against the same snapshot.
  • Lightning Connections fixes it because opening the screen runs lightningRepo.sync() (LightningConnectionsScreen.kt:90-92, LightningConnectionsViewModel.kt:151-152), whose success path calls syncState().

Why the snapshot stayed stale for 3+ minutes in that run is not explained: node start runs sync() right after connectToTrustedPeers() (LightningRepo.kt:434-441), and a successful sync calls syncState(). The stuck send's log was not saved.

Expected behavior

While the node has channels and none reads usable, Bitkit re-reads the channel list, so a reconnected channel is usable within about a second without a visit to Lightning Connections.

Steps to Reproduce

These are the steps of that one run on 25 Sep, not a recipe that triggers it on demand:

  1. Use a wallet with one Lightning channel to the LSP.
  2. Open a contact and tap Pay.
  3. Wait for "Connecting to network" to clear; the amount screen offers only Savings. Continue: the confirm screen stays on "Connecting to network".
  4. Open Settings › Advanced › Lightning Connections, go back and tap Pay again: Spending is offered.

I did not find out how the stale state arose in that run. Backgrounding the app so its node stops and restarts is my guess at a trigger and was not run as such. On 30 Sep, on an Android emulator (API 36.1, regtest, one channel to the LSP), two natural attempts did not trigger it: disconnecting the LSP peer in the app (the channel read not usable and the peer did not come back on its own for 100 s), and a cold start with the network off, then on (the app's own refresh ran 40 ms after the channel re-established, so the state was fresh).

Logs / Screenshots / Recordings

The log of the stuck send was not saved. The lines below are from a different run the same day, a wallet setup on an Android emulator (Bitkit dev 2.5.0 (190), regtest): a node start read the channel as not usable 23 ms before LDK logged it reconnected. Fields are elided, timestamps are as logged.

00:51:48.246 LightningRepo: Collected channel support summary for 'trusted peers connected': channelId='e6f5…f356', … ready='true', usable='false'
00:51:48.269 LDK: Reconnected channel e6f5…f356 with no loss

Bitkit Version

Bitkit dev 2.5.0 (190), regtest, 25 Sep 2026. The code cited above was read on master 4d13a1d, not on that build.

Device / OS

Android emulator, API 36.1

Reproducibility

Rarely (once or twice)

Seen once on 25 Sep; not reproduced in the attempts on 30 Sep.

Additional context

Proposal:

  • In waitForUsableChannels(), while channels exist and none is usable, re-read the channel list every second until one is usable or CHANNELS_USABLE_TIMEOUT ends, as the empty-list branch already does once. Re-read channels and peers only; syncState() also calls listBalances (see [Bug]: Node.listBalances ANR in receive flow #1036).
  • While SendSheet shows the overlay for unusable channels, run the same re-read, so the amount screen offers Spending once the channel is back.
  • Test: in LightningRepoTest, start with a state that holds one channel that is not usable, let the service report it usable, and assert that waitForUsableChannels() returns well before the timeout.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions