{"record":{"id":"b85ce7086b2218b3","repo":"datahaven-xyz/datahaven","slug":"providedfutureera","errorCode":"ProvidedFutureEra","errorMessage":"ProvidedFutureEra","messagePattern":"ProvidedFutureEra","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"operator/pallets/external-validator-slashes/src/lib.rs","lineNumber":409,"sourceCode":"            }\n            // insert back slashes\n            Slashes::<T>::insert(era, &era_slashes);\n            Ok(())\n        }\n\n        #[pallet::call_index(1)]\n        #[pallet::weight(T::WeightInfo::force_inject_slash())]\n        pub fn force_inject_slash(\n            origin: OriginFor<T>,\n            era: EraIndex,\n            validator: T::AccountId,\n            percentage: Perbill,\n            offence_kind: OffenceKind,\n        ) -> DispatchResult {\n            ensure_root(origin)?;\n            let active_era = T::EraIndexProvider::active_era().index;\n\n            ensure!(era <= active_era, Error::<T>::ProvidedFutureEra);\n\n            let slash_defer_duration = T::SlashDeferDuration::get();\n\n            let _ = T::EraIndexProvider::era_to_session_start(era)\n                .ok_or(Error::<T>::ProvidedNonSlashableEra)?;\n\n            let next_slash_id = NextSlashId::<T>::get();\n\n            let slash = compute_slash::<T>(\n                percentage,\n                next_slash_id,\n                era,\n                validator,\n                slash_defer_duration,\n                offence_kind,\n            )\n            .ok_or(Error::<T>::ErrorComputingSlash)?;\n","sourceCodeStart":391,"sourceCodeEnd":427,"githubUrl":"https://github.com/datahaven-xyz/datahaven/blob/edcb13dbbcd3c29489eaa2480a6f60ee4cb1f3ec/operator/pallets/external-validator-slashes/src/lib.rs#L391-L427","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nforce_inject_slash(origin, future_era, validator, pct, kind);\n// after\nlet active_era = T::EraIndexProvider::active_era().index;\nensure!(era <= active_era);\nforce_inject_slash(origin, era, validator, pct, kind);","handlingStrategy":"validation","validationCode":"const activeEra = (await api.query.staking.activeEra()).unwrap().index;\nif (era > activeEra) {\n  throw new Error(`cannot inject slash for future era ${era} > ${activeEra}`);\n}","typeGuard":"function isPastOrActiveEra(era, activeEra) {\n  return era <= activeEra;\n}","tryCatchPattern":"try {\n  await forceInjectSlash(era, validator, pct, kind);\n} catch (e) {\n  if (String(e).includes('ProvidedFutureEra')) {\n    console.error('Era not yet active; wait for rollover and retry');\n  }\n}","preventionTips":["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"],"tags":["staking","slashing","substrate","era"],"backgroundTag":"invalid-state-transition","analyzedSha":"edcb13dbbcd3c29489eaa2480a6f60ee4cb1f3ec","analyzedAt":"2026-09-13T19:19:32.206Z","contentChangedAt":"2026-09-13T19:19:32.206Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}