pydantic/monty · error
Dereferenced found while converting to MontyObject
Error message
Dereferenced found while converting to MontyObject
What it means
Same boundary rule as the Undefined case: Value::Dereferenced is a memory-model-checks-only sentinel for a released heap object and must never be converted into a MontyObject. The panic fires when a dereferenced value reaches the host-object conversion under the `memory-model-checks` feature.
Source
Thrown at crates/monty/src/object_bridge.rs:617
position: file.position(),
})
}
HeapReadOutput::ExtFunction(function) => Self::Function {
name: function.get(vm.heap).as_str().to_owned(),
docstring: None,
},
_ => repr_or_error(object, vm),
};
// Remove from visited set after processing
visited.remove(id);
result
}
Value::Builtin(Builtins::Type(t)) => Self::Type(MontyType::from_internal(*t, vm)),
Value::Builtin(Builtins::ExcType(e)) => Self::Type(MontyType::Exception(*e)),
Value::Builtin(Builtins::Function(f)) => Self::BuiltinFunction(*f),
#[cfg(feature = "memory-model-checks")]
Value::Dereferenced => panic!("Dereferenced found while converting to MontyObject"),
_ => repr_or_error(object, vm),
}
}
}
/// Crate-internal bridge between [`MontyType`] and the runtime [`Type`].
///
/// `MontyType` lives in `monty-types` (it is pure data), but mapping it to and
/// from the runtime `Type` needs heap/intern access, so the conversions stay
/// here as a `pub(crate)` extension trait.
pub(crate) trait MontyTypeExt: Sized {
fn to_internal(&self) -> Option<Type>;
fn from_internal_static(ty: Type) -> Self;
fn from_internal(ty: Type, vm: &mut VM<'_>) -> Self;
}
View on GitHub (pinned to adc986b362)
Solutions
- Fix the path that kept the stale Value alive after its heap entry was dereferenced (guard with defer_drop!/DropGuard).
- Ensure containers implement DropWithContext so their elements are released before the container crosses the bridge.
- Re-run without the feature to confirm scope; then reproduce with `cargo test --features memory-model-checks` on the relevant test binary.
Example fix
// before let value = self.pop(); heap.dec_ref(id); // value stale afterwards let obj = MontyObject::from_value(value, vm)?; // after let value = self.pop(); defer_drop!(value, heap); // released on every path before any conversion // build the MontyObject from a live value instead
Defensive patterns
Strategy: type-guard
Validate before calling
// ensure the value is live before conversion
if matches!(value, Value::Dereferenced) { return Err(BridgeError::stale_value()); } Type guard
fn is_dereferenced(v: &Value) -> bool { matches!(v, Value::Dereferenced) } Prevention
- Use defer_drop!/DropGuard for every owned heap-backed value
- Give containers DropWithContext impls so elements release together
- Run `cargo test --features memory-model-checks` for the touched test binaries
When it happens
Trigger: Running with `memory-model-checks` and converting a Value::Dereferenced via the bridge — a heap entry was freed/dereferenced but the Value was still alive at the conversion point, typically because a refcount drop path left a stale reference in a container or on the stack.
Common situations: Memory-model CI runs after changes to heap.rs, drop_with paths, or container cleanup; a leaked stale value is then returned to the host.
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
- Cannot get identity of Dereferenced object
- gather commit frame id is not a GatherFuture
- gather item is not a Coroutine, ExternalFuture, or GatherFut
- invalid ascii byte
- Undefined found while converting to MontyObject
AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13).
Data as JSON: /api/errors/c4b3d82e1ee4ed96.
Report an issue: GitHub.