Skip to content

Sub 1k sat credit balance makes sends fail via a swap remainder below min_vtxo_amount #1164

Description

@GeorgeTsagk

Summary

On mainnet with a wavewalletrpc + swapruntime build (v0.1.2-rc1), an offchain send fails when the wallet holds a credit balance smaller than the payment amount.

The daemon builds a mixed settlement: it spends the available credit, then tries to cover the remainder with an ark swap leg. When that remainder is below the operator min_vtxo_amount (1000 sat), the OOR transfer for the swap leg is rejected and the whole send stalls. It never reaches a terminal state on the client (the SEND entry stays PENDING and the CLI blocks until timeout), and the recipient is not paid.

Environment

  • Network: mainnet
  • Wallet backend: lwwallet
  • Build: waved / wavecli v0.1.2-rc1 (tags wavewalletrpc, swapruntime)
  • Operator policy: min_vtxo_amount_sat = 1000, dust_limit = 1000

Repro

  1. Get the wallet into a state where it holds a credit balance below the operator min_vtxo_amount. For example, 700 sat of credit available, left over after a prior sub 1k credit send.
  2. Pay a BOLT11 invoice for an amount above the credit balance, but where (amount - credit) is below min_vtxo_amount. Example: pay a 1000 sat invoice with 700 sat of credit available, so the swap remainder is 300 sat.
  3. Run the offchain send for that invoice.

Expected

The send either completes, or it fails fast with an actionable error. The daemon should not construct a swap leg below min_vtxo_amount. Reasonable options:

  • top up the credit instead of splitting,
  • fall back to a full swap that does not consume the partial credit, or
  • return a clear error up front.

Actual

The send splits into a mixed settlement whose swap remainder is below min_vtxo_amount. The operator rejects the OOR transfer for that leg, the SEND entry stays PENDING, and the CLI blocks until it is canceled by the wait timeout. The credit is tied up until the swap deadline passes, after which it refunds and the balance reconciles. No funds are lost, but the payment silently does not go through.

Daemon logs

Two separate reproductions:

2026-08-19 21:21:16.957 [WRN] SWAP: pay swap d0aa6472e33c8e8394d281a7353a7f691e4cdedd006b4ac7c42040aac0cf1f84 stopped: fund vHTLC: send oor transfer: rpc error: code = InvalidArgument desc = recipient 0: amount 300 below operator min_vtxo_amount_sat 1000
2026-08-20 10:10:53.421 [INF] SWAP: In-swap created hash=9f5d86e3690d1beb0a93f0ac14148bd7b6cd2665022a0e366acd79cb4d32c7b7 amount_sat=300 fee_sat=0 settlement_type=mixed deadline="2026-08-20 10:19:03 +0000 UTC"
2026-08-20 10:10:53.915 [WRN] SWAP: pay swap 9f5d86e3690d1beb0a93f0ac14148bd7b6cd2665022a0e366acd79cb4d32c7b7 stopped: fund vHTLC: send oor transfer: rpc error: code = InvalidArgument desc = recipient 0: amount 300 below operator min_vtxo_amount_sat 1000

CLI output

Second reproduction:

{
  "status": "PENDING",
  "kind": "SEND",
  "amount_sat": -300,
  "fee_sat": 0,
  "payment_hash": "9f5d86e3690d1beb0a93f0ac14148bd7b6cd2665022a0e366acd79cb4d32c7b7"
}
{
  "error": {
    "code": "CANCELED",
    "message": "canceled while waiting for 9f5d86e3690d1beb0a93f0ac14148bd7b6cd2665022a0e366acd79cb4d32c7b7; last phase: settling",
    "retryable": false
  }
}

Notes

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions