datahaven-xyz/datahaven · warning · Error
EmptyTargets
EmptyTargets
Error message
EmptyTargets
What it means
Sentinel dispatch error returned by cancel_deferred_slash when the caller supplies an empty slash_indices vector: there are no deferred slash entries to look up and cancel, so the extrinsic refuses to proceed rather than performing a no-op root call. The input at fault is the slash_indices argument, which must contain at least one valid index into the deferred slash report for the given era.
Solutions
- Check `slash_indices` length and skip the extrinsic call when it is empty.
- Fix the off-chain query producing indices so it selects the intended deferred slashes.
- If all slashes were already cancelled, treat this as a no-op instead of submitting the transaction.
Example fix
// before
cancel_deferred_slash(origin, era, indices);
// after
if !indices.is_empty() {
cancel_deferred_slash(origin, era, indices);
} Defensive patterns
Strategy: validation
Validate before calling
if (!slashIndices.length) {
return; // nothing to cancel, skip transaction
} Type guard
function hasSlashIndices(indices) {
return Array.isArray(indices) && indices.length > 0;
} Try / catch
try {
await cancelDeferredSlash(era, indices);
} catch (e) {
if (String(e).includes('EmptyTargets')) {
console.warn('No slashes to cancel; treating as no-op');
}
} Prevention
- Guard automation scripts to skip the call when no indices are collected
- Log the query results that produce indices for auditability
- Distinguish 'already cancelled' from 'never existed' before batching
When it happens
Trigger: Calling `cancel_deferred_slash(origin, era, vec![])` — typically from an off-chain automation that collected no matching slash indices, or a UI passing an unfiltered empty selection.
Common situations: Batch scripts canceling slashes computed by a query that returned no rows, or a governance proposal generated from stale data where all slashes were already cancelled.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
AI-assisted analysis of datahaven-xyz/datahaven@edcb13dbbc (2026-09-13).
Data as JSON: /api/errors/fe6627c6d9433839.
Report an issue: GitHub.
Appendix: source
Thrown at operator/pallets/external-validator-slashes/src/lib.rs:374
#[pallet::weight(T::WeightInfo::cancel_deferred_slash(slash_indices.len() as u32))]
pub fn cancel_deferred_slash(
origin: OriginFor<T>,
era: EraIndex,
slash_indices: Vec<u32>,
) -> DispatchResult {
ensure_root(origin)?;
let active_era = T::EraIndexProvider::active_era().index;
// We need to be in the defer period
ensure!(
era <= active_era
.saturating_add(T::SlashDeferDuration::get().saturating_add(One::one()))
&& era > active_era,
Error::<T>::DeferPeriodIsOver
);
ensure!(!slash_indices.is_empty(), Error::<T>::EmptyTargets);
ensure!(
is_sorted_and_unique(&slash_indices),
Error::<T>::NotSortedAndUnique
);
// fetch slashes for the era in which we want to defer
let mut era_slashes = Slashes::<T>::get(era);
let last_item = slash_indices[slash_indices.len().saturating_sub(1)];
ensure!(
(last_item as usize) < era_slashes.len(),
Error::<T>::InvalidSlashIndex
);
// Remove elements starting from the highest index to avoid shifting issues.
for index in slash_indices.into_iter().rev() {
era_slashes.remove(index as usize);
}
// insert back slashesView on GitHub (pinned to edcb13dbbc)