How to clear a structural flag.
June 2026
When a depleted channel keeps failing to refill at a price it can ever earn back, the node stops grinding it and raises a structural flag — a "this is a capital decision, not a pricing problem" signal. A common question follows: once flagged, does it ever clear, or is it stuck forever? It clears — but the path is narrower than you'd expect, and one obvious recovery case is deliberately ignored. This note explains both.
What is the structural flag, exactly?
It is a live verdict, recomputed every run, not a sticky state someone has to reset. Two conditions must both hold:
structural = profit_capped AND failures_since_last_success ≥ THRESHOLD profit_capped means the channel is calibrated (enough
trailing outbound volume to trust its earnings) and the price it would take to
refill it has escalated past what it earns back —
earned_ppm × PROFIT_HORIZON. THRESHOLD is
REBALANCE_STRUCTURAL_FAIL_THRESHOLD (5) consecutive failed refill
attempts. When both are true the planner drops the channel as a rebalance
target, a one-time structural_liquidity alert fires, and
structural_flag_ts is stamped.
When does the timestamp get stamped?
By both the 2h fee loop and the nightly recompute, through one shared
helper (_structural_flag_ts): first-stamp on entry, kept while it
persists, cleared to 0 on recovery. Whichever job runs first stamps it, so the
flag trips within one 2h cycle rather than waiting up to a day for the nightly
pass. The alert is gated on the prior stamp, so it still fires exactly once.
Does it have to fail 5 real attempts?
Not necessarily — a failed cycle can now also be a QueryRoutes
early-out. Before spending an attempt, the planner probes the cheapest
chunk for a live route within the channel's affordable ceiling (a dry-run, no
payment). If there's none, refilling is a capital problem, not price discovery, so
it skips the wasted attempt and records a synthetic failed cycle
(failure_reason='QR_NO_AFFORDABLE_ROUTE') that counts toward the
threshold exactly like a real refusal. The point: the early-out replaces the
wasted attempts, not the stranding they would eventually trigger — the
channel still reaches its structural flag and surfaces the capital decision, just
without burning cycles probing routes that can't settle. It's calibrated-only, and
a probe that's unavailable (LND down) is never counted, so a transport
blip can't strand a channel. See rebalancing.
So how does it clear?
The helper writes 0 on the next run where the verdict goes false — which means flipping either term back. There are five ways:
1. A successful refill → failures_since_last_success resets to 0 → not structural
2. Earnings climb → earned_ppm × PROFIT_HORIZON > escalated → not profit_capped
3. Channel goes UNJUDGED → too little volume over the FULL max lookback (90d) → cap evaporates
4. Liquidity recovers → local_ratio ≥ REBALANCE_TARGET (≥50%) → structural cleared outright
5. Failures EXPIRE → refusals older than the max lookback (90d) stop counting → fails < 5 Paths 1–3 are covered below; path 4 — the recovery escape — is covered under "Does refilling the channel clear it?"
Path 5 mirrors path 3: failure evidence ages out on the same 90-day
clock as earnings evidence. There's a subtle honesty argument behind it —
a profit-capped channel's failed attempts all bid the cap price, not
the escalated levels the formula imagines, so carrying those refusals forever
would inflate any future re-entry bid with prices that were never actually
tested. With expiry, a channel returning to planning resumes at
last_refill × 1.0 and rebuilds escalation from fresh attempts —
and a flag nothing else clears earns a free 5-attempt re-probe roughly once a
quarter: if the market still refuses, it re-flags within hours at zero cost;
if routing prices moved, the channel quietly comes back to life.
Why doesn't it just clear on its own, then?
Because of a deliberate blind spot in path 1. A successful rebalance is what
normally zeroes the failure counter — but the planner drops structural
targets, so the pipeline never attempts a refill into a flagged channel,
so it never produces the success that would clear it. The counter stays frozen
at ≥ threshold. Left purely to the auto-loop on a steady sink, the flag
persists — which is arguably correct, since it is a standing capital
decision. To clear it via path 1 you have to act: an operator-forced rebalance
(ln-operator rebalance --force …) that actually lands.
What about paths 2 and 3?
Path 2 (earnings climb past the cap) is real but rarely fires on a true sink —
it needs the channel to start earning far more on outbound than the refill
costs, which is exactly what wasn't happening. Path 3 is the quiet one: if a
flagged channel goes idle long enough that its outbound volume drops below
EARNED_PPM_MIN_VOLUME_SATS over the entire max lookback
(EARNED_PPM_MAX_LOOKBACK_DAYS, 90 days), it falls back to
calibrating — there's no longer enough evidence to cap it — so
profit_capped goes false and the flag clears.
Path 3 used to be much sharper than it sounds. The calibration window was a flat
21 days, and a structural channel is quiet because it's depleted —
so the window reliably drained, the cap evaporated after three quiet weeks,
and the budget that came back was the full failure-escalation
(last_refill × (1 + 0.2 × failures), clipped at
REBALANCE_MAX_BUDGET_PPM): a channel the gate had ruled
unprofitable at 1,400 ppm would silently re-enter planning bidding 5,000.
The fix: the earned-ppm window now widens when the standard
21 days are too quiet — doubling (21 → 42 → 84 → 90) until the volume
suffices — so adverse evidence ages out gradually instead of expiring at a
cliff. Path 3 still exists, but it's realistic only after ~3 months of
silence, by which point the stale evidence arguably should stop
counting.
Does refilling the channel clear it?
Yes — there's a fourth, automatic path: liquidity recovery.
If the channel's local_ratio climbs back to
REBALANCE_TARGET (≥50%), the structural verdict is cleared
regardless of earnings or failure history — a channel that's no longer
depleted isn't a structural emergency. This is what retires the alarm when the
inbound-fee discount (or any organic flow) actually refills the channel.
⚠️ Attention: the escape uses strong hysteresis — it trips below 20% local and only clears at ≥50%, so it can't flap on a channel hovering near the edge. It clears only thestructuralescalation;profit_capped(the budget cap) is unaffected, since earnings vs refill cost haven't changed. The flag and its timestamp clear within one 2h fee-loop cycle of recovery.
The short answer
The flag clears on the next run after the channel refills back to target, a successful (often operator-forced) rebalance, a real earnings recovery, the channel falling back to calibrating for lack of volume, or its failure evidence expiring (~90d, the quarterly re-probe). The one thing the auto-pipeline won't do is pay to refill a flagged channel while the flag stands — so if organic flow never brings it back, the fastest fixes remain yours: force a successful rebalance, or make the capital call the flag is asking for (open inbound / splice / close).