tursodatabase/turso · error · ValueError
size must be non-negative
Error message
size must be non-negative
What it means
Cursor.fetchmany(size) raises ValueError when size is negative. When size is None it falls back to cursor.arraysize, which matches the stdlib sqlite3 behavior. The check exists only for negative numbers; zero is legal and returns an empty list.
Solutions
- Call fetchall() when you want every remaining row
- Clamp the computed size: cur.fetchmany(max(0, size))
- Fix the pagination arithmetic so remaining rows never go negative
Example fix
# before rows = cur.fetchmany(limit - fetched_so_far) # -5 on the last page # after rows = cur.fetchmany(max(0, limit - fetched_so_far))
Defensive patterns
Strategy: validation
Validate before calling
def fetchmany_safe(cur, size):
if size is None:
return cur.fetchmany()
if size < 0:
raise ValueError("size must be >= 0; use fetchall() for all rows")
return cur.fetchmany(size) Try / catch
try:
rows = cur.fetchmany(size)
except ValueError:
rows = cur.fetchall() # negative size usually means 'everything' was intended Prevention
- Use fetchall() when you want all remaining rows
- Clamp computed page sizes with max(0, n)
- Do not port the '-1 means all' convention from other client libraries
When it happens
Trigger: Calling cur.fetchmany(-1), often intending 'give me everything' as some other APIs allow; a size computed from pagination arithmetic such as limit - already_fetched that underflows to negative.
Common situations: Developers coming from APIs where -1 means 'all rows'; pagination code whose remaining-count math goes negative at the last page.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Named parameters are not supported; use positional…
- query timeout must be non-negative
- Cannot operate on a closed cursor
- executemany() requires a single DML…
- batch mode must be one of
AI-assisted analysis of tursodatabase/turso@c1e5928725 (2026-08-20).
Data as JSON: /api/errors/97e2e4083477b187.
Report an issue: GitHub.
Appendix: source
Thrown at bindings/python/turso/lib.py:1103
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 c1e5928725)