ElementsProject / ElementsProject/lightning
xpay: "Could not create payment onion: path too long!" on BOLT12 offers with large embedded TLVs (has FIXME)
- Dominant language
- C
- Stars
- 3.1k
- Forks
- 1k
- Avg merge
- 4d 10h
- Merged PRs (30d)
- 13
Description
### Summary
When using `xpay` (and the surrounding payment plugins: renepay, askrene) to pay certain BOLT12 offers that carry large amounts of embedded data in their TLVs, xpay fails during onion construction with:
```
Could not create payment onion: path too long!
```
(with RPC error code 209 / `PAY_UNSPECIFIED_ERROR`).
The failure originates here:
https://github.com/ElementsProject/lightning/blob/master/plugins/xpay/xpay.c (around the `do_inject` function)
```c
onion = create_onion(tmpctx, attempt, effective_bheight);
/* FIXME: Handle this better! */
if (!onion) {
payment_give_up(aux_cmd, attempt->payment, PAY_UNSPECIFIED_ERROR,
"Could not create payment onion: path too long!");
return command_still_pending(aux_cmd);
}
```
The underlying cause is `create_onionpacket(...)` returning NULL when `sphinx_path_payloads_size(sp) > ROUTING_INFO_SIZE`.
### Observed symptoms
- The BOLT12 offers in question contain long `invoice` / offer metadata (hundreds of bytes of extra TLV data for payout tracking / recipient verification). This inflates the final serialized onion far beyond what a "normal length" route would use.
- Route selection still proposes paths that later fail at the onion creation step.
- In the same payment attempts we also saw many `plugin-cln-renepay` failures with `code=202 "Malformed error reply"` and very large `onionreply` blobs.
- The node in question has very low channel count (only 2 active channels), which makes longer routes more common and the size limit easier to hit.
- The error was surfaced to end users via a higher-level plugin (`cln4go-plugin` doing custom "ocean-pay" logic) during real production Lightning payout processing.
### Steps to reproduce (conceptual)
1. Have a node with limited channels.
2. Attempt to pay a BOLT12 offer (`lni1...` / `lno1...`) whose encoded invoice/offer contains substantial extra TLV data.
3. xpay / the payment attempt reaches `create_onion` → size check fails.
### Expected behavior
- Either the route finder (askrene + xpay/renepay) should account for the *final serialized onion size* (including extra BOLT12 TLVs) when selecting paths, or
- xpay should handle the failure more gracefully (try a shorter route / more parts / clearer error with hop count + payload size, etc.), and
- the error message returned to the caller / user should be more actionable than the current generic "path too long".
### Version / environment
- Observed on a custom/modded build based on v26.04 (and v25 on another instance)
- Using `xpay`, `renepay`, `askrene`, plus custom BOLT12 handling on top (`cln4go-plugin`)
- Full log excerpts and the exact failing offer (with tracking ID in the offer description) available if needed for reproduction.
### Additional context
This was discovered while debugging a user-facing payout error on an experimental Ocean.xyz Lightning node (`el.ocean.xyz`).
The `FIXME: Handle this better!` comment suggests this case was already known to be suboptimal.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.