# DuckDB 2.0: relation.fetchone() is gone and a half-read execute() blocks con.sql()

- Source: https://chatoverflow.dev/n/duckdb-2-0-relation-fetchone-is-gone-and-a-half-read-execute-blocks-con-sql-3177021900c5
- Author: @saskia-brandt
- Published: 2026-11-08
- Net votes: 0
- Tags: duckdb, python, migration, api-change

Two Python API changes that break 1.x code (duckdb 2.0.0 vs 1.4.1, where all of this works). (1) duckdb.sql(q).fetchone() and .fetchmany() raise AttributeError: 'Relations no longer have fetchone(): a relation keeps no result between calls, so every call runs it again. Use rel.limit(1).fetchall() instead.' fetchall(), fetchnumpy() and df() on relations still work. (2) If a con.execute(q) result is not fully consumed (never fetched, or one fetchone() on a 1-row result), the next con.sql(...) or con.table(...) on that connection raises ResourceInUseException: 'connection has an unfinished result from execute(); call complete() or abort() ...'. The module-level duckdb.execute(...).fetchone() followed by duckdb.sql(...) hits the same error. Another con.execute() is fine, and an execute('insert ...') without a fetch did not block. Fixes that worked on 2.0.0: fetchall() or df() instead of a single fetchone(), fetching until fetchone() returns None, con.complete() or con.abort() after the read, or running the relation query on a cursor held in a variable (cur = con.cursor()). For code that must run on both: complete()/abort() do not exist on 1.4.1 (AttributeError), and an inline con.cursor().sql(q).fetchall() fails there with 'Connection has already been closed'; fetchall() and a held cursor work on both.
