pydantic/monty · critical

DeleteCell: entry is not a Cell

Error message

DeleteCell: entry is not a Cell

What it means

`delete_cell` (executed by the DeleteCell opcode, e.g. `del x` on a closed-over variable) swaps `Undefined` into the heap Cell behind a local slot; this panic fires when the entry at `cell_id` is not a `Cell`. It signals heap type-tag corruption or an interpreter bug, not a user-facing error — deleting an unbound cell would raise Python-level NameError instead.

Source

Thrown at crates/monty/src/bytecode/vm/mod.rs:2561

            panic!("StoreCell: entry is not a Cell")
        };
        mem::swap(&mut cell.get_mut(this.heap).0, value);
    }

    /// Unbinds a closure cell: replaces its contents with `Undefined`, so a
    /// later [`Self::load_cell`] raises the free-variable `NameError` —
    /// CPython's `DELETE_DEREF` cleanup of a captured `except ... as` target.
    /// The only emitter stores `None` first, so the cell is never already
    /// unbound here (no error path, unlike [`Self::delete_global`]).
    fn delete_cell(&mut self, slot: u16) {
        let value = Value::Undefined;
        // the guard drops the cell's previous contents after the swap
        let this = self;
        defer_drop_mut!(value, this);

        let cell_id = this.cell_id_from_local(slot);
        let HeapReadOutput::Cell(mut cell) = this.heap.read(cell_id) else {
            panic!("DeleteCell: entry is not a Cell")
        };
        mem::swap(&mut cell.get_mut(this.heap).0, value);
    }
}

// `heap` is not a public field on VM, so this implementation needs to go here rather than in `heap.rs`
impl ContainsHeap for VM<'_> {
    fn heap(&self) -> &Heap {
        self.heap
    }
    fn heap_mut(&mut self) -> &mut Heap {
        self.heap
    }
}

/// Ensures proper reference-counting cleanup when the VM goes out of scope.
///
/// Drains exception stack, operand stack, globals, scheduler state, and JSON

View on GitHub (pinned to adc986b362)

Solutions

  1. Report the reproducer to Monty maintainers
  2. Audit cell drop/dec_ref paths for frees that leave a stale HeapId in the local slot
  3. Run the memory-model-checks test binary over cell/closure tests

Example fix

// not applicable — internal invariant violation
Defensive patterns

Strategy: fallback

Try / catch

// Internal panic — no user-side catch; isolate and report.
match monty.run(code, limits) {
    Ok(res) => res,
    Err(e) => report_bug(code, e),
}

Prevention

When it happens

Trigger: Executing `del <cellvar>` when the cell HeapId in the local slot resolves to a non-Cell heap entry; reachable only through heap corruption or an interpreter defect.

Common situations: Fuzzing; changing cell lifecycle code (creation, drop, cycle collection); a patch reusing HeapIds across heap types.

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/70f21f73442c4dc1. Report an issue: GitHub.