Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save vincenzopalazzo/073f3b7b438e03aa8c27b8c684093f7d to your computer and use it in GitHub Desktop.

Select an option

Save vincenzopalazzo/073f3b7b438e03aa8c27b8c684093f7d to your computer and use it in GitHub Desktop.
You are working in the OCEAN mining dashboard / payout codebase.
Goal:
Improve the Lightning payout error UX so users stop seeing vague messages like:
"Unknown payout error, contact lightning@ocean.xyz"
Most Lightning payout failures are temporary route/liquidity/reachability issues, and OCEAN retries automatically. The UI should classify the raw CLN/lightning error into a user-friendly category, show a clear status and action, hide raw technical details behind an expandable section, and only tell users to contact support after sensible thresholds.
Context:
Lightning payments can fail transiently because routing depends on channel liquidity, stale gossip, intermediary nodes, and pathfinding. Public research confirms that LN routes often fail because balances are private and network information can be stale; retries may succeed later. See:
- Lightning payments use local graph knowledge, while channel balances are not public, so intermediary-hop failures are expected and retries are normal.
- Empirical LN reliability studies show routing success depends on amount and stale network information.
- BOLT onion routing means many failures happen along the route, not necessarily at OCEAN or the recipient wallet.
Implementation requirements:
1. Find where dashboard / API currently renders or stores Lightning payout errors.
Search for strings like:
- "Unknown payout error"
- "contact lightning@ocean.xyz"
- "Latest lightning error"
- "Raw error"
- "cln err code"
- "No route found"
- "Timeout waiting for response"
2. Add a classifier for Lightning payout errors.
Create a function similar to:
classifyLightningError(rawError: string, context?: LightningErrorContext): LightningErrorCategory
Suggested categories:
TEMPORARY_ROUTE_OR_LIQUIDITY
CUSTODIAL_WALLET_ROUTE_UNAVAILABLE
SELF_HOSTED_ROUTE_OR_LIQUIDITY
RECIPIENT_UNREACHABLE
INVALID_BOLT12_OFFER
KNOWN_CLN_PATH_TOO_LONG
PAYOUT_PENDING_RETRYING
UNKNOWN_BUT_RETRYING
Suggested matching logic:
KNOWN_CLN_PATH_TOO_LONG:
- "Could not create payment onion: path too long"
- "path too long"
RECIPIENT_UNREACHABLE:
- "Node unreachable"
- "Timeout waiting for response"
- "Unable to connect"
- "no address known for peer"
- "could not route or connect"
- "cln err code: 1003"
- "cln err code: `1003`"
- "cln err code: 1005"
- "cln err code: `1005`"
INVALID_BOLT12_OFFER:
- offer rejected
- invalid offer
- amount field in offer
- signature verification failed
- offer memo/address mismatch
- BOLT12 field contains a Bitcoin address instead of an offer
TEMPORARY_ROUTE_OR_LIQUIDITY:
- "temporary_channel_failure"
- "fee_insufficient"
- "No route found"
- "Could not find route"
- "could not find a usable set of paths"
- "Timed out after"
- "Failed after"
- "cln err code: 205"
- "cln err code: `205`"
- "cln err code: 209"
- "cln err code: `209`"
- "cln err code: 210"
- "cln err code: `210`"
If context indicates the user is using LEXE/CoinOS/another custodial wallet, map route/liquidity errors to:
CUSTODIAL_WALLET_ROUTE_UNAVAILABLE
If context indicates a self-hosted node, custom node pubkey, onion address, or Core Lightning node, map route/liquidity errors to:
SELF_HOSTED_ROUTE_OR_LIQUIDITY
Otherwise use:
TEMPORARY_ROUTE_OR_LIQUIDITY
3. Add user-facing copy for each category.
Do not show "contact lightning@ocean.xyz" as the default message.
Copy:
TEMPORARY_ROUTE_OR_LIQUIDITY
Title:
Lightning payout delayed — OCEAN will retry automatically
Body:
We could not find a working Lightning route for this payout attempt. This is usually temporary and does not mean your sats are lost. Your unpaid balance remains with OCEAN and we will retry after future OCEAN blocks.
Action:
No action is required yet. If this continues for more than 7 days, contact support with your mining address.
Technical details:
Raw CLN error: {rawError}
CUSTODIAL_WALLET_ROUTE_UNAVAILABLE
Title:
Lightning payout delayed — wallet route unavailable
Body:
OCEAN could not find a working Lightning route to your wallet provider right now. You usually do not need to change anything. OCEAN will retry automatically after future OCEAN blocks.
Action:
If this continues for more than 7 days, try another supported BOLT12 wallet or contact support with your mining address.
Technical details:
Raw CLN error: {rawError}
SELF_HOSTED_ROUTE_OR_LIQUIDITY
Title:
Lightning payout delayed — check your node’s incoming route
Body:
OCEAN could not find a usable route to your Lightning node. Having inbound liquidity helps, but your peers also need to be able to route the payout from OCEAN to you.
Action:
Check that your node is online, reachable, has enough inbound liquidity, and has well-connected public peers. OCEAN will retry automatically.
Technical details:
Raw CLN error: {rawError}
RECIPIENT_UNREACHABLE
Title:
Lightning payout delayed — your node or offer is unreachable
Body:
OCEAN could not reach your Lightning node or BOLT12 offer to request the payout invoice.
Action:
Make sure your node is online, your BOLT12 offer is still active, your node is reachable over Tor if applicable, and your node is visible on Lightning gossip. Restarting your Lightning node may help. OCEAN will retry automatically.
Technical details:
Raw CLN error: {rawError}
INVALID_BOLT12_OFFER
Title:
Lightning setup issue — update your BOLT12 offer
Body:
OCEAN could not use the BOLT12 offer configured for this mining address.
Action:
Create a new amountless BOLT12 offer, configure it on OCEAN, and sign it with the Bitcoin address used as your OCEAN username. Make sure the BOLT12 field contains an offer, not a Bitcoin address.
Technical details:
Raw CLN error: {rawError}
KNOWN_CLN_PATH_TOO_LONG
Title:
Lightning payout delayed — known Core Lightning path issue
Body:
OCEAN could not build a valid payment path because the route was too long. Your unpaid balance is not lost. OCEAN will retry automatically, but this issue may require a different route or a backend fix.
Action:
If this continues for more than 48 hours, contact support with your mining address.
Technical details:
Raw CLN error: {rawError}
UNKNOWN_BUT_RETRYING
Title:
Lightning payout delayed — OCEAN will retry automatically
Body:
The latest Lightning payout attempt failed, but your unpaid balance is not lost. OCEAN will retry automatically after future OCEAN blocks.
Action:
If this continues for more than 3 days, contact support with your mining address.
Technical details:
Raw CLN error: {rawError}
4. Add escalation logic.
Create something like:
shouldShowContactSupport(category, failedAttempts, ageHours)
Rules:
INVALID_BOLT12_OFFER:
false by default; show setup instructions instead.
KNOWN_CLN_PATH_TOO_LONG:
show support CTA if failedAttempts >= 2 OR ageHours >= 48.
RECIPIENT_UNREACHABLE:
show support CTA if failedAttempts >= 3 OR ageHours >= 48.
TEMPORARY_ROUTE_OR_LIQUIDITY:
CUSTODIAL_WALLET_ROUTE_UNAVAILABLE:
SELF_HOSTED_ROUTE_OR_LIQUIDITY:
show support CTA if failedAttempts >= 6 OR ageHours >= 168.
UNKNOWN_BUT_RETRYING:
show support CTA if failedAttempts >= 3 OR ageHours >= 72.
Before threshold, the UI should say:
"No action required yet — OCEAN will retry automatically."
After threshold, say:
"If this continues, contact support with your mining address."
5. Improve the dashboard UI.
Replace the current single error block with structured fields:
Status:
Lightning payout delayed
Reason:
Category-specific title/reason
Action:
Category-specific user action
Retry info, if available:
Last failed attempt: {timestamp}
Failed attempts since last success: {count}
Last successful Lightning payout: {timestamp or "none yet"}
Next automatic retry: after the next eligible OCEAN block
Technical details:
Collapsed by default.
Contains raw CLN error and raw code.
6. Preserve raw error visibility for debugging.
Do not remove raw errors from backend/API logs.
Do not hide them from advanced users entirely.
Just make them collapsed/secondary in the dashboard.
7. Add tests.
Add unit tests for the classifier with examples:
- "cln err code: `205` - message `Failed: We could not find a usable set of paths...`"
=> TEMPORARY_ROUTE_OR_LIQUIDITY
- "cln err code: `209` - message `Timed out after after 5 attempts. We got temporary_channel_failure...`"
=> TEMPORARY_ROUTE_OR_LIQUIDITY
- "cln err code: `209` - message `Could not create payment onion: path too long!`"
=> KNOWN_CLN_PATH_TOO_LONG
- "Latest lightning error: Node unreachable Raw error: cln err code: `1003`..."
=> RECIPIENT_UNREACHABLE
- "cln err code: `1005` - Timeout waiting for response"
=> RECIPIENT_UNREACHABLE
- "No route found Raw error: cln err code: `210`"
=> TEMPORARY_ROUTE_OR_LIQUIDITY
- "offer rejected because amount field is present"
=> INVALID_BOLT12_OFFER
- route error with context.walletType = "custodial"
=> CUSTODIAL_WALLET_ROUTE_UNAVAILABLE
- route error with context.walletType = "self_hosted"
=> SELF_HOSTED_ROUTE_OR_LIQUIDITY
8. Add integration/snapshot tests for the dashboard copy.
Verify:
- Generic route failures no longer show "contact lightning@ocean.xyz".
- Support CTA is hidden before threshold.
- Support CTA appears after threshold.
- Raw CLN error is still available under technical details.
- Invalid BOLT12 offer shows setup instructions, not "wait."
9. Keep wording short and non-blaming.
Avoid:
"your wallet is broken"
"OCEAN failed"
"unknown error"
"contact support" as the default
Prefer:
"Lightning payout delayed"
"OCEAN will retry automatically"
"Your unpaid balance is not lost"
"No action required yet"
"Check node reachability/liquidity" only when relevant
Deliverables:
- Classifier function and types.
- Message mapping function.
- Escalation function.
- Dashboard UI update.
- Unit tests and UI tests.
- Remove/replace generic "Unknown payout error, contact lightning@ocean.xyz" for classified cases.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment