tursodatabase/turso · error · ValueError
infinite float values cannot be sent over the protocol
Error message
infinite float values cannot be sent over the protocol
What it means
Before running a batch, _prevalidate_batch_parameters scans every parameter value and rejects floats that are +inf or -inf, because the wire protocol has no representation for infinite float values. The check raises a plain ValueError and the batch is wrapped via _batch_statement_error with the failing statement index. NaN and finite floats pass; only infinities are rejected.
Solutions
- Replace infinite values with None (NULL) or a large finite sentinel before binding.
- Sanitize parameters: convert inf to None via a helper applied to the params tuple/dict.
- If inf must round-trip, store it as TEXT ('Infinity') or a REAL max value instead.
- Catch the error and identify which statement index failed via the wrapped _batch_statement_error, then fix that statement's parameters.
Example fix
# before
cur.execute_batch = conn.batch([("INSERT INTO t VALUES (?)", (float('inf'),)])
# after
params = [None if isinstance(v, float) and math.isinf(v) else v for v in (float('inf'),)]
conn.batch([("INSERT INTO t VALUES (?)", tuple(params))]) Defensive patterns
Strategy: validation
Validate before calling
import math
def sanitize(v):
if isinstance(v, float) and math.isinf(v):
return None # store NULL instead of inf
return v
params = tuple(sanitize(v) for v in raw_params) Type guard
import math
def is_protocol_safe_float(v: object) -> bool:
return not (isinstance(v, float) and math.isinf(v)) Try / catch
try:
conn.batch(stmts)
except ValueError as e:
if "infinite float" in str(e):
stmts = [(sql, tuple(sanitize(v) for v in params)) for sql, params in stmts]
conn.batch(stmts)
else:
raise Prevention
- Never use float('inf') as a sentinel value for DB parameters.
- Sanitize numpy/computed values that may overflow to inf.
- Replace infinity with NULL, TEXT 'Infinity', or a finite max sentinel.
- Validate parameters at your API boundary before they reach the driver.
When it happens
Trigger: batch() (or the equivalent path in execute) where any positional or named parameter is float('inf'), float('-inf'), or a computed value like 1e400 that evaluates to inf, e.g. ("SELECT ?", (float('inf'),)).
Common situations: Inserting results of numpy computations that overflowed to inf, logging timings where a division by zero produced inf, and defaults like float('inf') used as a sentinel 'unbounded' value being sent to the database.
Related errors
- batch mode must be one of
- batch mode must be one of
- batch response does not have one result and one error per…
- batch response is missing the result for statement
- batch statement must be a SQL string or a (sql, parameters)…
AI-assisted analysis of tursodatabase/turso@c1e5928725 (2026-08-31).
Data as JSON: /api/errors/5644d9479348aa78.
Report an issue: GitHub.
Appendix: source
Thrown at bindings/python/turso/lib.py:673
return results
def _prevalidate_batch_parameters(
self, stmts: list[tuple[str, Sequence[Any] | Mapping[str, Any]]]
) -> list[tuple[str, Sequence[Any] | Mapping[str, Any]]]:
validator = self._conn.prepare_single("SELECT ?")
validated = []
try:
for index, (sql, parameters) in enumerate(stmts):
try:
if isinstance(parameters, Mapping):
copied_parameters: Sequence[Any] | Mapping[str, Any] = dict(parameters)
values = copied_parameters.values()
else:
copied_parameters = Cursor._to_positional_params(parameters)
values = copied_parameters
for value in values:
if isinstance(value, float) and math.isinf(value):
raise ValueError(
"infinite float values cannot be sent over the protocol"
)
validator.bind_positional(1, value)
except Exception as exc: # noqa: BLE001
raise _batch_statement_error(index, _map_turso_exception(exc)) from exc
validated.append((sql, copied_parameters))
finally:
validator.finalize()
return validated
def _run_batch_statements(
self, stmts: list[tuple[str, Sequence[Any] | Mapping[str, Any]]]
) -> list[BatchResult]:
"""Execute the statements of a batch in order, stopping at the
first failure and reporting its index along with the results of
the statements that completed."""
results = []
for index, (sql, parameters) in enumerate(stmts):View on GitHub (pinned to c1e5928725)