astral-sh/ruff · error

argument index should be valid

Error message

argument index should be valid

What it means

CallArguments::insert_type stores the inferred type for the argument at `index`; the items vector holds one entry per call argument, so the index must have been produced against the same arguments list. The expect is an index-bounds panic: the passed index is >= items.len().

Source

Thrown at crates/ty_python_semantic/src/types/call/arguments.rs:217

    pub(crate) fn is_variadic(&self, index: usize) -> bool {
        self.items.get(index).is_some_and(|argument| {
            matches!(argument.argument, Argument::Variadic | Argument::Keywords)
        })
    }

    pub(crate) fn argument_types(&self, index: usize) -> Option<&CallArgumentTypes<'db>> {
        self.items.get(index).map(|item| &item.types)
    }

    pub(crate) fn insert_type(
        &mut self,
        index: usize,
        tcx: impl Into<TypeContext<'db>>,
        ty: Type<'db>,
    ) {
        self.items
            .get_mut(index)
            .expect("argument index should be valid")
            .types
            .insert(tcx, ty);
    }

    pub(crate) fn clear_types(&mut self, index: usize) {
        self.items
            .get_mut(index)
            .expect("argument index should be valid")
            .types = CallArgumentTypes::default();
    }

    pub(crate) fn iter_types(&self) -> impl Iterator<Item = &CallArgumentTypes<'db>> + '_ {
        self.items.iter().map(|item| &item.types)
    }

    /// Returns `true` if the inferred types are equal for the given set of argument indices.
    pub(crate) fn inferred_types_equal_at(&self, other: &Self, argument_indices: &[usize]) -> bool {
        argument_indices.iter().all(|&index| {

View on GitHub (pinned to d1087a4b9e)

Solutions

  1. Minimize the call expression (defaults/star-args/overloads are common ingredients) and file a ty issue with the backtrace
  2. As a contributor: derive indices and argument-type writes within the same pass, or use `get_mut` and skip out-of-range indices instead of unwrapping
  3. Check for nondeterminism by re-running the file several times; intermittent behavior points at iteration-order instability

Example fix

// before
self.items.get_mut(index).expect("argument index should be valid").types.insert(tcx, ty);

// after
if let Some(item) = self.items.get_mut(index) {
    item.types.insert(tcx, ty);
}
Defensive patterns

Strategy: validation

Validate before calling

debug_assert!(index < arguments.items_len(), "stale argument index");
if index < arguments.items_len() {
    arguments.insert_type(index, tcx, ty);
}

Prevention

When it happens

Trigger: Replaying an argument index captured in an earlier inference pass after the arguments list changed (fixpoint re-inference, mutation between passes), or a mismatch between the number of parameters matched and the number of arguments actually recorded for the call.

Common situations: Nondeterministic inference order across fixpoint iterations; calls mixing defaults, *args/**kwargs, and overloads where the matcher's index arithmetic drifts from the recorded arguments.

Related errors


AI-assisted analysis of astral-sh/ruff@d1087a4b9e (2026-08-20). Data as JSON: /api/errors/85c37108a96daf74. Report an issue: GitHub.