Skip to content

[bug]: force closures hanging - blocks_til_maturity negative - peer is connected and online! #10767

@dynamicscript

Description

@dynamicscript

Pre-Submission Checklist

  • I have searched the existing issues and believe this is a new bug.
  • I am not asking a question about how to use lnd, but reporting a bug (otherwise open a discussion).

LND Version

v0.20.1

LND Configuration

[Application Options]
debuglevel=info
maxpendingchannels=5
accept-keysend=true
blockcachesize=104857600
ignore-historical-gossip-filters=1
#Disable
listen=0.0.0.0:9735
minchansize=500000
#Disablestagger-initial-reconnect=1
dust-threshold=500000
rpcmiddleware.enable=true
gc-canceled-invoices-on-startup=true
#New options
gossip.ban-threshold=20
gossip.msg-rate-bytes=524288
gossip.msg-burst-bytes=1048576
gossip.filter-concurrency=10
num-restricted-slots=200
#numgraphsyncpeers=3

[db]
db.backend=postgres

[postgres]
db.postgres.dsn=postgresql:/*********************sslmode=disable
db.postgres.timeout=0
db.postgres.maxconnections=32

#nat=true

#listen=localhost

Your router must support and enable UPnP, otherwise delete this line

#nat=true

[Bitcoin]
bitcoin.active=1
bitcoin.basefee=0
bitcoin.feerate=600

enable either testnet or mainnet

#bitcoin.testnet=1
bitcoin.mainnet=1
bitcoin.node=bitcoind

Watchtower

#watchtower.active=1
#wtclient.active=true

[autopilot]
autopilot.active=0
#autopilot.maxchannels=35
#autopilot.allocation=0.2

add / change the following options within [Application Options]:

#listen=localhost

add:

[Tor]
tor.active=true
tor.v3=true
tor.streamisolation=false
tor.password=*******************
#listen=localhost
#Disable
##tor.skip-proxy-for-clearnet-targets=true
tor.skip-proxy-for-clearnet-targets=true
#sync-freelist=1

[protocol]

; If set, then lnd will create and accept requests for channels larger than 0.16
; BTC
protocol.wumbo-channels=true
#maxchansize=100000000
#routerrpc.maxmchistory=10000

protocol.custom-message=513
protocol.custom-nodeann=39
protocol.custom-init=39

[bolt]
#db.bolt.auto-compact=1

[gossip]
#ignore-historical-filters=true
#gossip.pinned-syncers=03cde60a6323f7122d5178255766e38114b4722ede08f7c9e0c5df9b912cc201d6
#gossip.pinned-syncers=037f66e84e38fc2787d578599dfe1fcb7b71f9de4fb1e453c5ab85c05f5ce8c2e3
#gossip.pinned-syncers=03a93b87bf9f052b8e862d51ebbac4ce5e97b5f4137563cd5128548d7f5978dda9

[healthcheck]

#The number of times we should attempt to query our chain backend before
#gracefully shutting down. Set this value to 0 to disable this health check.
healthcheck.chainbackend.attempts=5

#The amount of time we allow a call to our chain backend to take before we fail
#the attempt. This value must be >= 1s.
#healthcheck.chainbackend.timeout=30s

#The amount of time we should backoff between failed attempts to query chain
#backend. This value must be >= 1s.
#healthcheck.chainbackend.backoff=2m

#The amount of time we should wait between chain backend health checks. This
#value must be >= 1m.
#healthcheck.chainbackend.interval=1m

#The amount of time we allow a call to our chain backend to take before we fail
#the attempt. This value must be >= 1s.
healthcheck.chainbackend.timeout=30s

#The amount of time we should backoff between failed attempts to query chain
#backend. This value must be >= 1s.
healthcheck.chainbackend.backoff=5m

#The amount of time we should wait between chain backend health checks. This
#value must be >= 1m.
healthcheck.chainbackend.interval=5m

[caches]
caches.channel-cache-size=35000

Backend Version

v29.3.knots20260210

Backend Configuration

bitcoin.conf configuration file. Lines beginning with # are comments.

proxy=127.0.0.1:9050 #If you use Windows, this could possibly be 127.0.0.1:9150 in some cases.
##onion=127.0.0.1:9050 #If you use Windows, this could possibly be 127.0.0.1:9150 in some cases.
listen=1
##externalip=jwuhlwpce5tlaasxvhgxcbrlictjsayqymgeggtyfk4i4btkgcyhhpyd.onion
listenonion=0
#bind=127.0.0.1
##discover=1
#bind=127.0.0.1:27382=onion
#onlynet=onion
walletbroadcast=0
deprecatedrpc=warnings
datacarrier=0
printtoconsole=1
#debug=tor

How many recent blocks to check at startup. (0 == check all blocks which is very slow!)

checkblocks=3

How thorough the block verification of -checkblocks is (0-4).

checklevel=2

#torpassword=*********************

Network-related settings:

Run on the test network instead of the real bitcoin network.

#testnet=0

Run a regression test network

#regtest=0

Connect via a SOCKS5 proxy

#proxy=127.0.0.1:9050

Bind to given address and always listen on it. Use [host]:port notation for IPv6

#bind=

Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6

#whitebind=

##############################################################

Quick Primer on addnode vs connect

Let's say for instance you use addnode=4.2.2.4

addnode will connect you to and tell you about the

nodes connected to 4.2.2.4. In addition it will tell

the other nodes connected to it that you exist so

they can connect to you.

connect will not do the above when you 'connect' to it.

It will only connect you to 4.2.2.4 and no one else.##

So if you're behind a firewall, or have other problems

finding nodes, add some using 'addnode'.

If you want to stay private, use 'connect' to only

connect to "trusted" nodes.

If you run multiple nodes on a LAN, there's no need for

all of them to open lots of connections. Instead

'connect' them all to one node that is port forwarded

and has lots of connections.

Thanks goes to [Noodle] on Freenode.

##############################################################

Use as many addnode= settings as you like to connect to specific peers

#addnode=69.164.218.197
#addnode=10.0.0.2:8333

#addnode=viize3apqmtbzoixt3kozr7ktwc5nm5peuwtuvsvjtvpyhodxz72kgid.onion:8333
#addnode=zp4tcgwjp4ft3n7uixiy5gczvap2xqgrrn2rvqlbua5bilbcijj5nyid.onion:8333
#addnode=efb76sinj3pb2w5ccxfocva5illszoezibp72aeun3o3muj7ruubkiqd.onion:8333
#addnode=zd73wn25pqncfnfescjk44qo2w4c7zfa3qd7srtwr5txfxctb2e5ouyd.onion:8333
#addnode=db46sq2zq5yvnee7ck5vagowk4iajt5wpt6afxxgeajnuzcnbg4lcgad.onion:8333
#addnode=2rqo67d37skm5tthprwttedmicwmjvcp2uv2jbxrvaantmp6zy4swkyd.onion:8333
#addnode=x537bgk6paye2nze4xh23yhzw4qknmchoapec6skk3s5cepmzucwn5yd.onion:8333
#addnode=3wkvjatqxzxmluowapxupqmgccdbol6r2k5ilkp7h4baw6zawpb43wqd.onion:8333

Alternatively use as many connect= settings as you like to connect ONLY to specific peers

#connect=69.164.218.197
#connect=10.0.0.1:8333

Listening mode, enabled by default except when 'connect' is being used

#listen=1

Maximum number of inbound+outbound connections.

maxconnections=20

JSON-RPC options (for controlling a running Bitcoin/bitcoind process)

server=1 tells Bitcoin-Qt and bitcoind to accept JSON-RPC commands

server=1

Bind to given address to listen for JSON-RPC connections. Use [host]:port notation for IPv6.

This option can be specified multiple times (default: bind to all interfaces)

#rpcbind=

If no rpcpassword is set, rpc cookie auth is sought. The default -rpccookiefile name

is .cookie and found in the -datadir being used for bitcoind. This option is typically used

when the server and client are run as the same user.

If not, you must set rpcuser and rpcpassword to secure the JSON-RPC API.

The config option rpcauth can be added to server startup argument. It is set at initialization time

using the output from the script in share/rpcauth/rpcauth.py after providing a username:

./share/rpcauth/rpcauth.py alice

String to be appended to bitcoin.conf:

rpcauth=alice:f7efda5c189b999524f151318c0c86$d5b51b3beffbc02b724e5d095828e0bc8b2456e9ac8757ae3211a5d9b16a22ae

Your password:

DONT_USE_THIS_YOU_WILL_GET_ROBBED_8ak1gI25KFTvjovL3gAM967mies3E=

On client-side, you add the normal user/password pair to send commands:

rpcuser=pi123
#rpcpassword=DONT_USE_THIS_YOU_WILL_GET_ROBBED_8ak1gI25KFTvjovL3gAM967mies3E=
rpcpassword=*****************
server=1
#daemon=1
#listen=1
txindex=1
rpcuser=bitcoinrpc
rpcpassword=*********
zmqpubrawblock=tcp://127.0.0.1:18501
zmqpubrawtx=tcp://127.0.0.1:18502

uacomment=********************************

#Default wallet
wallet=/data/bitcoin/default

You can even add multiple entries of these to the server conf file, and client can use any of them:

rpcauth=bob:b2dd077cb54591a2f3139e69a897ac$4e71f08d48b4347cf8eff3815c0e25ae2e9a4340474079f55705f40574f4ec99

How many seconds bitcoin will wait for a complete RPC HTTP request.

after the HTTP connection is established.

#rpcclienttimeout=30

By default, only RPC connections from localhost are allowed.

Specify as many rpcallowip= settings as you like to allow connections from other hosts,

either as a single IPv4/IPv6 or with a subnet specification.

NOTE: opening up the RPC port to hosts outside your local trusted network is NOT RECOMMENDED,

because the rpcpassword is transmitted over the network unencrypted.

server=1 tells Bitcoin-Qt to accept JSON-RPC commands.

it is also read by bitcoind to determine if RPC should be enabled

#rpcallowip=10.1.1.34/255.255.255.0
#rpcallowip=1.2.3.4/24
#rpcallowip=2001:db8:85a3:0:0:8a2e:370:7334/96

Listen for RPC connections on this TCP port:

rpcport=8332

You can use Bitcoin or bitcoind to send commands to Bitcoin/bitcoind

running on another host using this option:

rpcconnect=127.0.0.1

Wallet options

Create transactions that have enough fees so they are likely to begin confirmation within n blocks (default: 6).

This setting is over-ridden by the -paytxfee option.

#txconfirmtarget=n

Pay a transaction fee every time you send bitcoins.

#paytxfee=0.000x

Miscellaneous options

Pre-generate this many public/private key pairs, so wallet backups will be valid for

both prior transactions and several dozen future transactions.

#keypool=100

Enable pruning to reduce storage requirements by deleting old blocks.

This mode is incompatible with -txindex and -rescan.

0 = default (no pruning).

1 = allows manual pruning via RPC.

>=550 = target to stay under in MiB.

#prune=550

User interface options

Start Bitcoin minimized

#min=1

Minimize to the system tray

#minimizetotray=1
#maxmempool=1596
#maxmempool=32
#maxmempool=1000
blockreconstructionextratxn=1000000
#maxuploadtarget=4096
blockmaxsize=3985000
blockmaxweight=3985000

OS/Distribution

Linux 6.12.62+rpt-rpi-v8 #1 SMP PREEMPT Debian 1:6.12.62-1+rpt1 (2025-12-18) aarch64 GNU/Linux

Bug Details & Steps to Reproduce

Channels are being sporadically force closed and are not clearing.
I now have 5 force_close pending channels with negative blocks_til_maturity counts
Not all peers are online but some are.

Expected Behavior

I would have expected the force close channels to have closed by now returning balance to the wallet!

Debug Information

Here is one pending_force_closing_channels output I have removed peer infos - for the moment closing txid is valid
This particular peer is connected and online.

pending_force_closing_channels": [
{
"channel": {
"remote_node_pub": "",
"channel_point": "
:",
"capacity": "2500000",
"local_balance": "2068213",
"remote_balance": "138185",
"local_chan_reserve_sat": "0",
"remote_chan_reserve_sat": "0",
"initiator": "INITIATOR_LOCAL",
"commitment_type": "ANCHORS",
"num_forwarding_packages": "0",
"chan_status_flags": "",
"private": false,
"memo": "",
"custom_channel_data": ""
},
"closing_txid": "
*****",
"limbo_balance": "2068213",
"maturity_height": 943514,
"blocks_til_maturity": -2657,
"recovered_balance": "0",
"pending_htlcs": [],
"anchor": "LOST"
}
},

Environment

No response

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions