Symptom
Operator follows the failure-recovery hint from `scripts/anvil_fork.sh` and Notion cheat sheet:
```
export CHARON_PRICE_MAX_AGE_SECS=86400
cargo run --bin charon ... listen --execute ...
```
Bot still aborts with `feed 'BNB' is stale (updated N s ago, max_age 3600 s)` because the env var is never consulted. Documented escape hatch silently does nothing.
Root cause
`crates/charon-core/src/config.rs:141` claims:
```rust
/// fall back to the global default (`DEFAULT_MAX_AGE` / the
/// `CHARON_PRICE_MAX_AGE_SECS` env override). See #331.
```
`crates/charon-cli/src/main.rs:924-929` (and the `replay` path at :1668) wires the price cache with hardcoded `DEFAULT_MAX_AGE`:
```rust
let prices = Arc::new(PriceCache::with_per_symbol_max_age(
provider.clone(),
price_feeds,
DEFAULT_MAX_AGE,
per_symbol_max_age,
));
```
`grep -rn CHARON_PRICE_MAX_AGE_SECS crates/` returns one match — the docstring above. No call site reads the env var.
`scripts/anvil_fork.sh:75-77` also documents the var as a workaround for the stale-Chainlink case.
Proposed fix
Implement the env override at the CLI entry point: read `CHARON_PRICE_MAX_AGE_SECS` once, parse as `u64` seconds, default to `DEFAULT_MAX_AGE` on absence/parse failure (with a `tracing::warn!` on parse failure). Pass the resolved `Duration` to both `PriceCache::with_per_symbol_max_age` call sites. Per-symbol overrides in `[chainlink_max_age_secs.]` remain authoritative and continue to win.
Add a startup info log when the env override is active so operators see it took effect.
Impact
Documented operator escape hatch is non-functional. Forced fix today is editing `config/fork.toml` per-symbol values, which is brittle and survives across non-fork sessions if the operator forgets to revert.
Symptom
Operator follows the failure-recovery hint from `scripts/anvil_fork.sh` and Notion cheat sheet:
```
export CHARON_PRICE_MAX_AGE_SECS=86400
cargo run --bin charon ... listen --execute ...
```
Bot still aborts with `feed 'BNB' is stale (updated N s ago, max_age 3600 s)` because the env var is never consulted. Documented escape hatch silently does nothing.
Root cause
`crates/charon-core/src/config.rs:141` claims:
```rust
/// fall back to the global default (`DEFAULT_MAX_AGE` / the
/// `CHARON_PRICE_MAX_AGE_SECS` env override). See #331.
```
`crates/charon-cli/src/main.rs:924-929` (and the `replay` path at :1668) wires the price cache with hardcoded `DEFAULT_MAX_AGE`:
```rust
let prices = Arc::new(PriceCache::with_per_symbol_max_age(
provider.clone(),
price_feeds,
DEFAULT_MAX_AGE,
per_symbol_max_age,
));
```
`grep -rn CHARON_PRICE_MAX_AGE_SECS crates/` returns one match — the docstring above. No call site reads the env var.
`scripts/anvil_fork.sh:75-77` also documents the var as a workaround for the stale-Chainlink case.
Proposed fix
Implement the env override at the CLI entry point: read `CHARON_PRICE_MAX_AGE_SECS` once, parse as `u64` seconds, default to `DEFAULT_MAX_AGE` on absence/parse failure (with a `tracing::warn!` on parse failure). Pass the resolved `Duration` to both `PriceCache::with_per_symbol_max_age` call sites. Per-symbol overrides in `[chainlink_max_age_secs.]` remain authoritative and continue to win.
Add a startup info log when the env override is active so operators see it took effect.
Impact
Documented operator escape hatch is non-functional. Forced fix today is editing `config/fork.toml` per-symbol values, which is brittle and survives across non-fork sessions if the operator forgets to revert.