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

  1. Fix the path that kept the stale Value alive after its heap entry was dereferenced (guard with defer_drop!/DropGuard).
  2. Ensure containers implement DropWithContext so their elements are released before the container crosses the bridge.
  3. 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

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


AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13). Data as JSON: /api/errors/c4b3d82e1ee4ed96. Report an issue: GitHub.