tursodatabase/turso · error · ValueError
size must be non-negative
Error message
size must be non-negative
What it means
Cursor.fetchmany(size) requires size >= 0; a negative value raises ValueError (plain Python, not a DB-API error). When size is None it defaults to cursor.arraysize, and size 0 legally returns an empty list. There is no negative-means-all convention here — use fetchall() for everything remaining.
Source
Thrown at bindings/python/turso/lib.py:879
except TypeError:
_reject_stdlib_row_factory(rf)
raise
# Fallback: return tuple
return row_values
def fetchone(self) -> Any:
self._ensure_open()
row = self._fetchone_tuple()
if row is None:
return None
return self._apply_row_factory(row)
def fetchmany(self, size: Optional[int] = None) -> list[Any]:
self._ensure_open()
if size is None:
size = self.arraysize
if size < 0:
raise ValueError("size must be non-negative")
result: list[Any] = []
for _ in range(size):
row = self._fetchone_tuple()
if row is None:
break
result.append(self._apply_row_factory(row))
return result
def fetchall(self) -> list[Any]:
self._ensure_open()
result: list[Any] = []
while True:
row = self._fetchone_tuple()
if row is None:
break
result.append(self._apply_row_factory(row))
return result
View on GitHub (pinned to bad083fafb)
Solutions
- Use fetchall() when you want every remaining row
- Clamp computed sizes: cur.fetchmany(max(0, n))
- Pass None (or rely on arraysize) for the default batch size
Example fix
# before rows = cur.fetchmany(remaining - 1) # goes to -1 on the last page # after rows = cur.fetchmany(max(0, remaining - 1)) # or, when draining everything: rows = cur.fetchall()
Defensive patterns
Strategy: validation
Validate before calling
def safe_fetchmany(cur, size):
"""None -> arraysize; negative sizes are invalid, 0 returns []."""
if size is None or size >= 0:
return cur.fetchmany(size)
return cur.fetchall() # negative intent usually means 'everything remaining' Prevention
- Use fetchall() to drain remaining rows — never fetchmany(-1)
- Clamp paging arithmetic with max(0, n)
- Pass None to fall back to cursor.arraysize for the default batch
When it happens
Trigger: `cur.fetchmany(-1)` expecting all remaining rows (a convention some other DB-API drivers use), or a computed batch size that underflows to negative (e.g. rows_left going below zero in a paging loop).
Common situations: Code ported from drivers where fetchmany(-1) means unlimited; paging loops with off-by-one arithmetic on remaining counts.
Related errors
- retryFetch: attempts must be a finite integer >= 1, got ${at
- no SQL statements to execute
- autocommit must be True, False, or 'LEGACY'
- query timeout must be non-negative
- autocommit must be True, False, or 'LEGACY'
AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16).
Data as JSON: /api/errors/97e2e4083477b187.
Report an issue: GitHub.