pydantic/monty · error

Cannot get identity of Dereferenced object

Error message

Cannot get identity of Dereferenced object

What it means

Value::identity() panics when called on a Value::Dereferenced sentinel. Dereferenced is a memory-model-checks-only marker that replaces a value after its heap entry has been released; by design it has no identity. The panic asserts that no code path ever asks for the identity of a released object — hitting it means a value escaped the scope where dereferencing was recorded.

Source

Thrown at crates/monty/src/identity.rs:84

        match value {
            Value::Undefined => Self::Undefined,
            Value::Ellipsis => Self::Ellipsis,
            Value::NotImplemented => Self::NotImplemented,
            Value::None => Self::None,
            Value::Bool(value) => Self::Bool(*value),
            Value::Int(value) => Self::Int(*value),
            Value::Float(value) => Self::Float(value.to_bits()),
            Value::InternString(id) => Self::InternString(id.index()),
            Value::InternBytes(id) => Self::InternBytes(id.index()),
            Value::InternLongInt(id) => Self::InternLongInt(id.index()),
            Value::Builtin(builtin) => Self::Builtin(*builtin),
            Value::ModuleFunction(function) => Self::ModuleFunction(*function),
            Value::DefFunction(id) => Self::DefFunction(id.index()),
            Value::Marker(marker) => Self::Marker(*marker),
            Value::Property(property) => Self::Property(*property),
            Value::Ref(id) => Self::Heap(id.index()),
            #[cfg(feature = "memory-model-checks")]
            Value::Dereferenced => panic!("Cannot get identity of Dereferenced object"),
        }
    }

    /// Builds the identity of an arena-allocated object.
    pub(crate) fn from_heap_id(id: HeapId) -> Self {
        Self::Heap(id.index())
    }

    /// Encodes this key as the nonnegative integer exposed by Python's `id()`.
    pub(crate) fn encoded(&self) -> u128 {
        let payload = match self {
            Self::Undefined | Self::Ellipsis | Self::NotImplemented | Self::None => 0,
            Self::Bool(value) => u128::from(*value),
            Self::Int(value) => u128::from(zigzag_i64(*value)),
            Self::Float(bits) => u128::from(compact_float_bits(*bits)),
            Self::InternString(index)
            | Self::InternBytes(index)
            | Self::InternLongInt(index)

View on GitHub (pinned to adc986b362)

Solutions

  1. Do not compute identity on values that may be Dereferenced — check the variant first and handle it explicitly.
  2. Fix the refcount path that produced a stale Dereferenced value; the value should have been dropped or replaced before identity use.
  3. Reproduce without the memory-model-checks feature; in release builds the variant does not exist, confirming it is a checks-only invariant.
  4. Add a debug assertion or match arm upstream so Dereferenced never reaches identity computation.

Example fix

// before
let identity = ObjectIdentity::new(&value);
// after
match value {
    Value::Dereferenced => unreachable!(), // fix the stale-value path instead
    _ => { let identity = ObjectIdentity::new(&value); }
}
Defensive patterns

Strategy: type-guard

Validate before calling

// before computing identity
fn identity_safe(v: &Value) -> Option<ObjectIdentity> {
    if matches!(v, Value::Dereferenced) { None } else { Some(ObjectIdentity::new(v)) }
}

Type guard

fn is_dereferenced(v: &Value) -> bool { matches!(v, Value::Dereferenced) }

Prevention

When it happens

Trigger: Building an ObjectIdentity from a Value::Dereferenced while running with the `memory-model-checks` feature; a code path holds a Value after it was dereferenced and then computes its identity (e.g. for dict keys, `is` comparison, or hashing).

Common situations: Contributors running memory-model-checks CI after adding new opcodes or refcount paths; a new heap mutation path drops an entry but a stale Value is later used as an identity-bearing operand.

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