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

  1. Fetch `T::EraIndexProvider::active_era().index` immediately before the call and pass `era <= active_era`.
  2. Fix off-chain scripts to derive the era from pallet storage, not timestamps.
  3. 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

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)