pydantic/monty · error
validated gather awaitable is heap-backed
Error message
validated gather awaitable is heap-backed
What it means
`gather` validates its awaitable arguments earlier (rejecting non-heap objects), so `into_ref_id` is expected to succeed; this `expect` panics if a validated argument is not a heap reference. It encodes the invariant 'validation already ran, so every remaining item is a Ref'.
Solutions
- Check the validation block above this line covers every accepted awaitable type.
- Convert the expect into an explicit internal error if new value kinds are added.
- Report as a bug with the gather call that triggered it.
Example fix
// before
.map(|arg| arg.into_ref_id().expect("validated gather awaitable is heap-backed"))
// after
.map(|arg| arg.into_ref_id().map_err(|_| VmError::internal("gather awaitable not heap-backed")))
.collect::<RunResult<Vec<_>>>()?; Defensive patterns
Strategy: try-catch
Validate before calling
# In Monty Python code, only pass real awaitables to asyncio.gather assert all(hasattr(a, '__await__') for a in awaitables)
Try / catch
// Host-side (Rust embedding monty)
match result {
Err(MontyError::Panic(msg)) if msg.contains("heap-backed") => log_internal_bug(msg),
other => other?,
} Prevention
- Keep the validation loop above this line in sync with accepted types
- Add a unit test for each accepted awaitable kind
- Treat occurrence as a regression
When it happens
Trigger: Calling `asyncio.gather` in Monty code with an awaitable whose underlying `Value` is not a heap-backed `Value::Ref` but somehow passed the preceding validation — an interpreter bug, not user-reachable through normal Python code.
Common situations: Only from internal validation/refactoring drift: someone changes or reorders the validation loop and misses a non-ref case.
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
- already looked up
- Cannot get type of undefined value
- dict_items view must always reference a dict
- dict_items view must reference a dict
- dict_keys view must reference a dict
AI-assisted analysis of pydantic/monty@adc986b362 (2026-09-13).
Data as JSON: /api/errors/ba75046859ded46b.
Report an issue: GitHub.
Appendix: source
Thrown at crates/monty/src/modules/asyncio.rs:120
// so an invalid later argument needs no raw-HeapId rollback.
for arg in awaitables.iter() {
if !matches!(
arg,
Value::Ref(id)
if matches!(
vm.heap.get(*id),
HeapData::Coroutine(_) | HeapData::ExternalFuture(_) | HeapData::GatherFuture(_)
)
) {
return Err(ExcType::type_error(
"An asyncio.Future, a coroutine or an awaitable is required",
));
}
}
let items = awaitables
.drain(..)
.map(|arg| arg.into_ref_id().expect("validated gather awaitable is heap-backed"))
.collect();
let gather_future = GatherFuture::new(items);
let id = vm.heap.allocate(HeapData::GatherFuture(Box::new(gather_future)));
Ok(Value::Ref(id))
}
/// `asyncio.gather(*awaitables)` — variadic positional, no kwargs accepted.
///
/// `kwargs_not_supported_yet` rejects any kwarg with the macro's
/// "not yet implemented" `NotImplementedError`, replacing the previous
/// `TypeError: gather() takes no keyword arguments` from `into_pos_only`.
/// When CPython's `return_exceptions=False` is wired up this becomes a
/// regular `kw_only` slot and the flag goes away.
#[derive(FromArgs)]
#[from_args(name = "gather", kwargs_not_supported_yet)]
struct GatherArgs {
#[from_args(varargs)]
awaitables: Vec<Value>,View on GitHub (pinned to adc986b362)