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 JSONView on GitHub (pinned to adc986b362)
Solutions
- Report the reproducer to Monty maintainers
- Audit cell drop/dec_ref paths for frees that leave a stale HeapId in the local slot
- 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
- Run cell/closure tests under memory-model-checks after del/cell edits
- Never reuse HeapIds across heap types
- Report reproducers with the exact `del` statement
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
- LoadCell: entry is not a Cell
- StoreCell: entry is not a Cell
- list_extend: expected List on heap
- LoadCell/StoreCell: expected cell reference in local slot {s
- StableHeap::get - {id:?} out of bounds
AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13).
Data as JSON: /api/errors/70f21f73442c4dc1.
Report an issue: GitHub.