{"record":{"id":"2510a8d7c326d16c","repo":"pydantic/monty","slug":"gather-item-is-not-a-coroutine-externalfuture-or","errorCode":null,"errorMessage":"gather item is not a Coroutine, ExternalFuture, or GatherFuture","messagePattern":"gather item is not a Coroutine, ExternalFuture, or GatherFuture","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/monty/src/bytecode/vm/async_exec.rs","lineNumber":268,"sourceCode":"                }\n                HeapReadOutput::GatherFuture(child_gather) => {\n                    if let Some(value) = poll_settled_gather(&child_gather, self.heap)? {\n                        Poll::Ready(value)\n                    } else {\n                        drop(child_gather);\n                        // Both the inc_ref and the awaiter that owns it are\n                        // handed to the nested frame, which releases them when\n                        // it settles; until then nothing is committed for this\n                        // slot, so an error above needs no cleanup here.\n                        self.heap.inc_ref(gather_id);\n                        let sub_awaiter = Awaiter::GatherSlot {\n                            gather: gather_id,\n                            source: item_id,\n                        };\n                        return Ok(Some(self.open_gather_commit(item_id, sub_awaiter, Some(idx))));\n                    }\n                }\n                _ => panic!(\"gather item is not a Coroutine, ExternalFuture, or GatherFuture\"),\n            };\n\n            match poll {\n                Poll::Ready(value) => frame.results[idx] = Some(value),\n                Poll::Pending => {\n                    frame.pending_children.insert(item_id, smallvec![idx]);\n                }\n            }\n            frame.next += 1;\n        }\n\n        Ok(None)\n    }\n\n    /// Settles a fully-committed frame.\n    ///\n    /// With nothing left in flight the gather goes straight to `Completed` with\n    /// its result list (this covers the empty `gather()` too); otherwise it","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty/src/bytecode/vm/async_exec.rs#L250-L286","documentation":"When committing a gather, each item must be pollable: a Coroutine, ExternalFuture, or GatherFuture. If an item is anything else, this panic fires — the gather machinery only accepts awaitable-like values, so encountering another type means the earlier awaitability check or conversion is missing or heap state is corrupted.","triggerScenarios":"Internal: a gather() call contains an item that passed earlier validation but by commit time is not Coroutine/ExternalFuture/GatherFuture — e.g. an item replaced on the heap mid-commit, or a code path (like gather over a resolved non-awaitable) that skipped validation.","commonSituations":"Interpreter development on async_exec.rs; a gather fed results that were prematurely resolved or overwritten; heap corruption from a refcount bug.","solutions":["Verify gather items are awaited-eligible before constructing results (mirroring CPython's `An asyncio.Future, a coroutine or an awaitable is required` TypeError)","File a bug with the reproducing async snippet if hit from valid Python code","Run with --features memory-model-checks to hunt the underlying heap/refcount bug"],"exampleFix":"// before\nitems = gather([1, 2])  # non-awaitables must be rejected earlier\n\n// after\nitems = gather([coro1, coro2])  # only awaitables passed to gather","handlingStrategy":"validation","validationCode":"# user-side equivalent guard in Python\nitems = [it if asyncio.iscoroutine(it) or hasattr(it, '__await__') else ensure_future(it) for it in items]","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only pass awaitables (coroutines, futures, nested gathers) to gather()","Never mutate gather inputs while awaiting","Report panics from valid Python code as interpreter bugs"],"tags":["rust","async","gather","internal-invariant","interpreter"],"backgroundTag":"internal-invariant-violation","analyzedSha":"adc986b362e3961f407868cb118a99fe831b9e61","analyzedAt":"2026-09-13T19:19:18.698Z","contentChangedAt":"2026-09-13T19:19:18.698Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}