datahaven-xyz/datahaven · error · Error
ProvidedFutureEra
ProvidedFutureEra
Error message
ProvidedFutureEra
What it means
Thrown by the root-only `force_inject_slash` extrinsic when the supplied era is greater than the current `active_era`. Slashes can only be force-injected for eras that have already started (past or active), not for eras that have not begun yet.
Solutions
- Fetch `T::EraIndexProvider::active_era().index` immediately before the call and pass `era <= active_era`.
- Fix off-chain scripts to derive the era from pallet storage, not timestamps.
- If the intent is to pre-register a punishment, wait until that era becomes active and re-submit.
Example fix
// before force_inject_slash(origin, future_era, validator, pct, kind); // after let active_era = T::EraIndexProvider::active_era().index; ensure!(era <= active_era); force_inject_slash(origin, era, validator, pct, kind);
Defensive patterns
Strategy: validation
Validate before calling
const activeEra = (await api.query.staking.activeEra()).unwrap().index;
if (era > activeEra) {
throw new Error(`cannot inject slash for future era ${era} > ${activeEra}`);
} Type guard
function isPastOrActiveEra(era, activeEra) {
return era <= activeEra;
} Try / catch
try {
await forceInjectSlash(era, validator, pct, kind);
} catch (e) {
if (String(e).includes('ProvidedFutureEra')) {
console.error('Era not yet active; wait for rollover and retry');
}
} Prevention
- Derive era from pallet storage, not from timestamps or predictions
- Re-fetch activeEra right before submission to avoid rollover races
- Guard governance tooling UIs to only offer eras <= active era
When it happens
Trigger: Calling `force_inject_slash(origin, era, validator, percentage, offence_kind)` with `era > active_era` — e.g. manually targeting a future era index, or a script computing eras from wall-clock time rather than pallet state.
Common situations: Manual governance intervention with a mis-keyed era, off-chain tooling that predicts eras from timestamps and overshoots, or race conditions right at era rollover.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
AI-assisted analysis of datahaven-xyz/datahaven@edcb13dbbc (2026-09-13).
Data as JSON: /api/errors/b85ce7086b2218b3.
Report an issue: GitHub.
Appendix: source
Thrown at operator/pallets/external-validator-slashes/src/lib.rs:409
}
// insert back slashes
Slashes::<T>::insert(era, &era_slashes);
Ok(())
}
#[pallet::call_index(1)]
#[pallet::weight(T::WeightInfo::force_inject_slash())]
pub fn force_inject_slash(
origin: OriginFor<T>,
era: EraIndex,
validator: T::AccountId,
percentage: Perbill,
offence_kind: OffenceKind,
) -> DispatchResult {
ensure_root(origin)?;
let active_era = T::EraIndexProvider::active_era().index;
ensure!(era <= active_era, Error::<T>::ProvidedFutureEra);
let slash_defer_duration = T::SlashDeferDuration::get();
let _ = T::EraIndexProvider::era_to_session_start(era)
.ok_or(Error::<T>::ProvidedNonSlashableEra)?;
let next_slash_id = NextSlashId::<T>::get();
let slash = compute_slash::<T>(
percentage,
next_slash_id,
era,
validator,
slash_defer_duration,
offence_kind,
)
.ok_or(Error::<T>::ErrorComputingSlash)?;
View on GitHub (pinned to edcb13dbbc)