Skip to main content
What to do when the protocol stops pricing an asset. Read first: Oracles. The protocol fails closed on price. When a feed cannot be trusted, the affected flows revert rather than act on a doubtful number. An asset that stops pricing is the system working as designed, not a solvency event. Your job in an oracle disruption is to restore a trustworthy price, not to force a price through.

What fails closed, and what keeps working

No user funds move during an oracle disruption. The exposure is that liquidations pause on the affected markets, so a position that becomes unhealthy while the feed is down cannot be liquidated until pricing is restored.

Triage

Identify which of these you have before changing anything.

Feed nature and staleness budgets

This is the subtlest failure in the system and the one most likely to recur when listing a new asset. A feed has a FeedNature of either Market or Fundamental, and that choice changes how staleness is judged.
  • A push feed triggered by deviation only publishes when the price moves past a threshold. If the price is flat, no push is due, and the feed legitimately ages. Age is not a proxy for error on a deviation feed. A stale value means the price has not moved.
  • A heartbeat feed publishes on a fixed cadence. Age past that cadence genuinely indicates a problem.
Two bounds apply, and both must fit the feed:
  1. The leg’s own budget, max_stale_seconds. Must cover the feed’s slowest legitimate publication interval.
  2. The leg-age spread bound, MAX_LEG_AGE_SPREAD_SECONDS (3600s). This applies only when both legs are Market nature. It exists because the blend weights both legs equally, so a market leg far older than its market partner would drag the midpoint while each still satisfies its own budget. A Fundamental leg is exempt, because it prices a slow-moving quantity and its own bound is the intended budget.
Raising max_stale_seconds alone does not fix a slow feed paired with a fast one. If both legs are Market, the 3600s spread bound still applies, and a 12-hour-heartbeat feed can never stay within an hour of a five-minute Reflector leg. Marking the slow leg Fundamental is what turns the spread bound off.
When listing an asset, confirm the publication model of every leg before setting its budget. A deviation-triggered or long-heartbeat feed budgeted as Market with a short window will price correctly until the market goes quiet, then fail closed exactly when nothing is wrong.
Keep the leg budget below the reference’s own max_price_stale_seconds so the leg budget binds first and the failure points at the leg that caused it.

Blast radius

compose() reads the first source, and propagates a nested error before it reads the second. A failing reference therefore takes every dependent asset with it, even when those assets have a healthy standalone leg of their own, because the second source is never reached. When several assets fail together, look for a shared reference rather than diagnosing each asset separately. Repair the reference and the dependents recover. After changing an oracle, set_oracle re-probes dependents. A clean re-probe across all dependents is your confirmation that the repair reached them.

Repair

1

Confirm the failure class

Read the error code and the feed timestamps for both legs. Distinguish a feed that is genuinely down from a budget that does not fit the feed.
2

Decide whether the price is wrong or merely old

If the feed is publishing correctly and the value is simply old because the price has not moved, this is a configuration fault. If the feed has stopped publishing, this is a provider fault.
3

For a configuration fault, correct the leg definition

Set the nature and max_stale_seconds to match the feed’s real publication model. Submit through governance as an oracle update.
4

For a provider fault, wait or fail over

The protocol is already refusing to price, which is the safe state. Restore the provider, or move the asset to a different source through governance.
5

Verify the dependents

Confirm set_oracle re-probed every dependent without reverting, then read a price for each affected market.

Do not

  • Do not widen sanity bounds or tolerance bands to clear a stale error. Staleness and deviation are separate checks; widening bands does not fix age, and it removes a guard you will want during a real dislocation.
  • Do not unpause or force a price to unblock liquidations. A liquidation executed on an untrusted price is worse than a delayed liquidation.
  • Do not treat one asset’s failure as isolated until you have checked whether a shared reference is the cause.