pydantic/monty · error

dict_items view must always reference a dict

Error message

dict_items view must always reference a dict

What it means

Internal panic in the `DictItemsView::dict()` helper: the view's stored `dict_id` must always resolve to a Dict heap entry. The helper is used by items-view operations (comparison, conversion); reaching the panic means the view points at a non-Dict heap object, breaking the view invariant.

Source

Thrown at crates/monty/src/types/dict_view.rs:294

impl DictItemsView {
    /// Creates a new items view over an existing dictionary heap entry.
    #[must_use]
    pub fn new(dict_id: HeapId) -> Self {
        Self { dict_id }
    }

    /// Returns the underlying dictionary heap id.
    #[must_use]
    pub fn dict_id(self) -> HeapId {
        self.dict_id
    }
}

impl<'h> HeapRead<'h, DictItemsView> {
    fn dict(&self, vm: &mut VM<'h>) -> HeapObjectRead<'h, Dict> {
        let HeapReadOutput::Dict(dict) = vm.heap.read(self.get(vm.heap).dict_id) else {
            panic!("dict_items view must always reference a dict");
        };
        dict
    }

    /// Compares this items view to a mutable set using set membership semantics.
    pub(crate) fn eq_set(&self, other: &HeapRead<'h, Set>, vm: &mut VM<'h>) -> RunResult<bool> {
        dict_items_eq_set_like(
            &self.dict(vm),
            other.get(vm.heap).len(),
            |item, vm| other.contains(item, vm),
            vm,
        )
    }

    /// Compares this items view to a frozenset using set membership semantics.
    pub(crate) fn eq_frozenset(&self, other: &HeapRead<'h, FrozenSet>, vm: &mut VM<'h>) -> RunResult<bool> {
        dict_items_eq_set_like(
            &self.dict(vm),

View on GitHub (pinned to adc986b362)

Solutions

  1. File a bug with the reproducing snippet and full panic output.
  2. Verify every DictItemsView construction site stores the correct, live dict HeapId.
  3. Run memory-model-checks tests (`cargo test -p monty --features memory-model-checks`) on relevant test binaries to catch refcount errors.
Defensive patterns

Strategy: try-catch

Try / catch

match vm.heap.read(dict_id) {
    HeapReadOutput::Dict(d) => d,
    _ => return Err(internal_error("dict_items view lost its backing dict")),
}

Prevention

When it happens

Trigger: Any operation on a `dict.items()` view that calls the private `dict()` accessor (e.g. `eq_set` against a set, conversion to dict) while the view's dict_id resolves to a non-Dict entry — only via interpreter bugs or heap corruption.

Common situations: Encountered by Monty contributors during heap/refcount changes or when views outlive dictionary modifications in a buggy path; not reachable from valid Python code.

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/93924d21be30d91f. Report an issue: GitHub.