pydantic/monty · error

test function has a free variable

Error message

test function has a free variable

What it means

A panic raised by the memory-model test fault injector in `FunctionMetadata::corrupt_metadata_for_tests`. The `FreeVarLengthMismatch` fault pops a slot from `free_var_slots`, which only works when the function actually has free variables; `.expect("test function has a free variable")` panics when the list is empty. This is a test-harness bug (wrong fault kind applied to a function with no free vars), not a runtime error users can hit.

Source

Thrown at crates/monty/src/function.rs:319

                }
            })
        } else {
            None
        }
    }

    /// Injects a metadata fault for dump validation tests.
    #[cfg(feature = "test-hooks")]
    pub(crate) fn corrupt_metadata_for_tests(&mut self, fault: FunctionMetadataFault) {
        match fault {
            FunctionMetadataFault::SignatureSlotsBeyondNamespace => {
                self.namespace_size = self.signature.total_slots() - 1;
            }
            FunctionMetadataFault::NamespaceTooLarge => {
                self.namespace_size = usize::from(u16::MAX) + 1;
            }
            FunctionMetadataFault::FreeVarLengthMismatch => {
                self.free_var_slots.pop().expect("test function has a free variable");
            }
            FunctionMetadataFault::CellVarLengthMismatch => {
                self.cell_param_indices.pop().expect("test function has an owned cell");
            }
            FunctionMetadataFault::FreeVarSlotOutOfRange => {
                let slot = NamespaceId::new(self.namespace_size).expect("test namespace fits in u16");
                *self
                    .free_var_slots
                    .first_mut()
                    .expect("test function has a free variable") = slot;
            }
            FunctionMetadataFault::CellVarSlotOutOfRange => {
                let slot = NamespaceId::new(self.namespace_size).expect("test namespace fits in u16");
                *self
                    .cell_var_slots
                    .first_mut()
                    .expect("test function has an owned cell") = slot;
            }

View on GitHub (pinned to adc986b362)

Solutions

  1. Point the fault injection at a test function that closes over at least one free variable
  2. Choose a different `FunctionMetadataFault` variant appropriate to the function's actual metadata
  3. Guard the fault site: skip or fall back to another fault when `free_var_slots` is empty

Example fix

// before
FunctionMetadataFault::FreeVarLengthMismatch => {
    self.free_var_slots.pop().expect("test function has a free variable");
}

// after (test selection side)
let func = funcs.iter().find(|f| !f.free_var_slots.is_empty())
    .expect("fixture must include a function with free vars");
func.corrupt_metadata_for_tests(FunctionMetadataFault::FreeVarLengthMismatch);
Defensive patterns

Strategy: validation

Validate before calling

// Only apply FreeVarLengthMismatch to functions that have free variables.
fn can_inject(fault: Fault, meta: &FunctionMetadata) -> bool {
    match fault {
        Fault::FreeVarLengthMismatch => !meta.free_var_slots.is_empty(),
        Fault::CellVarLengthMismatch => !meta.cell_param_indices.is_empty(),
        _ => true,
    }
}

Prevention

When it happens

Trigger: Calling `corrupt_metadata_for_tests` with `FunctionMetadataFault::FreeVarLengthMismatch` on a `FunctionMetadata` whose `free_var_slots` vector is empty (e.g. a function with no closure captures).

Common situations: Writing a new memory-model/refcount test that applies the fault to a fixture function that has no free variables, or reusing a fault helper against a simplified test function.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13). Data as JSON: /api/errors/7981122301552a28. Report an issue: GitHub.