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

ValueError raised by encode_value() (protocol.py:38-44) when a bound parameter is a float equal to +inf or -inf. The SQL-over-HTTP protocol (section 8.2) has no encoding for infinities: JSON cannot carry them (the session even serializes with allow_nan=False), and unlike NaN — which becomes NULL because SQLite itself binds NaN as NULL — infinity is a meaningful REAL value that must not be silently rewritten, so the client refuses to send it.

Source

Thrown at serverless/python/turso_serverless/protocol.py:44

class ProtocolError(RuntimeError):
    """A transport failure or a response that violates the protocol."""


def encode_value(value: Any) -> dict:
    """Encode a Python value to a protocol value (section 8)."""
    if value is None:
        return {"type": "null"}
    if isinstance(value, bool):
        return {"type": "integer", "value": str(int(value))}
    if isinstance(value, int):
        return {"type": "integer", "value": str(value)}
    if isinstance(value, float):
        # The protocol forbids sending non-finite floats (section 8.2).
        if math.isnan(value):
            # SQLite binds NaN as NULL; JSON cannot carry it.
            return {"type": "null"}
        if math.isinf(value):
            raise ValueError("infinite float values cannot be sent over the protocol")
        return {"type": "float", "value": value}
    if isinstance(value, str):
        return {"type": "text", "value": value}
    if isinstance(value, (bytes, bytearray)):
        return {"type": "blob", "base64": base64.b64encode(value).decode("ascii")}
    raise TypeError(f"Unsupported value type: {type(value).__name__}")


def decode_value(pv: dict) -> Any:
    """Decode a protocol value (section 8) to a Python value."""
    try:
        typ = pv["type"]
        if typ == "null":
            return None
        if typ == "integer":
            return int(pv["value"])
        if typ == "float":
            raw = pv["value"]

View on GitHub (pinned to bad083fafb)

Solutions

  1. Check math.isinf(value) before binding and substitute NULL (if the column semantics allow) or reject the row
  2. Fix the upstream math: guard divide-by-zero and overflow before values reach the driver
  3. When ingesting JSON, parse with json.loads(..., parse_constant=lambda c: None) to map Infinity/NaN at the boundary

Example fix

// before
cur.execute("INSERT INTO metrics(v) VALUES (?)", (float('inf'),))

// after
v = float('inf')
cur.execute("INSERT INTO metrics(v) VALUES (?)", (None if math.isinf(v) else v,))
Defensive patterns

Strategy: validation

Validate before calling

import math


def sanitize_params(params):
    """The protocol cannot carry infinities; NaN is fine (binds as NULL)."""
    out = []
    for p in params:
        if isinstance(p, float) and math.isinf(p):
            raise ValueError("infinite float is not representable over the protocol")
        out.append(p)
    return out


cur.execute(sql, sanitize_params(params))

Type guard

import math


def is_bindable_number(v) -> bool:
    """True when encode_value will accept the float: finite, or NaN (-> NULL)."""
    return not isinstance(v, float) or math.isfinite(v) or math.isnan(v)

Try / catch

import math

try:
    cur.execute(sql, params)
except ValueError as e:
    if "infinite float" not in str(e):
        raise
    params = tuple(None if isinstance(p, float) and math.isinf(p) else p for p in params)
    cur.execute(sql, params)

Prevention

When it happens

Trigger: Binding math.inf / float('inf') / numpy.inf as a positional or named parameter; computed values that overflow (1e308 * 10); data loaded with Python's json module, which by default accepts the non-standard Infinity token and yields inf.

Common situations: ETL pipelines ingesting JSON logs containing Infinity; metrics code dividing without a zero guard and storing the result; pandas/numpy workflows converting np.inf to Python float before insert.

Related errors


AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16). Data as JSON: /api/errors/ee928da03a2483b8. Report an issue: GitHub.