Skip to content

lightningd: store raw failure message so waitsendpay always has raw_message#9342

Open
ksedgwic wants to merge 1 commit into
ElementsProject:masterfrom
ksedgwic:fix-waitsendpay-raw-message
Open

lightningd: store raw failure message so waitsendpay always has raw_message#9342
ksedgwic wants to merge 1 commit into
ElementsProject:masterfrom
ksedgwic:fix-waitsendpay-raw-message

Conversation

@ksedgwic

Copy link
Copy Markdown
Collaborator

Fixes the test_error_returns_blockheight CI flake (#9341).

waitsendpay builds its error from the live failure when it attaches while the payment is still pending, but when the HTLC failure completes first, wait_payment() rebuilds the error from the database - and the raw BOLT4 failure message was never persisted (/* FIXME: We don't store this! */ fail->msg = NULL;, dating to 2019). So data.raw_message silently disappears exactly when waitsendpay loses that race, which is what the test occasionally hits on CI (two master occurrences last week).

This PR adds a failmsg column to the payments table (with a downgrade drop for tools/lightning-downgrade), persists fail->msg when the failure is recorded, and reads it back in wait_payment(). Local and self-payment failures store NULL as before (no onion failure message exists for them), and pre-migration failed payments also return NULL, matching the old behavior.

The test now calls waitsendpay a second time after the failure is recorded, which deterministically exercises the database-replay path - verified that this assertion fails with exactly the CI flake's KeyError: 'raw_message' when the wait_payment change is reverted, and passes with it.

Fixes #9341

…essage

If a payment's HTLC failure completes before waitsendpay is called,
wait_payment() rebuilds the error from the database, which did not
persist the raw BOLT4 failure message: a 2019 FIXME in that path set
fail->msg = NULL, silently dropping raw_message from the error data.
This is the cause of the test_error_returns_blockheight CI flake -
the test loses the race occasionally, calls waitsendpay after the
failure has landed, and KeyErrors on the missing raw_message.

Add a failmsg column to the payments table (with a downgrade drop),
persist fail->msg when recording the failure, and read it back in
wait_payment.  Local and self-payment failures store NULL as before,
since no onion failure message exists for them; failed payments
recorded before this migration also return NULL, matching the old
behavior.

The flaky test now also calls waitsendpay a second time, which
deterministically takes the database-replay path, so the regression
is covered without any timing dependence.

Changelog-Fixed: JSON-RPC: `waitsendpay` error data now includes `raw_message` even when the payment already failed before the command was called.
Fixes: ElementsProject#9341
@ksedgwic
ksedgwic requested a review from nGoline July 21, 2026 21:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CI flake test_error_returns_blockheight (waitsendpay races the failure, loses raw_message)

1 participant