tursodatabase/turso · error · ValueError

measurements must be finite and positive

Error message

measurements must be finite and positive

What it means

positive_number() is the final gate for every numeric field and computed measurement: values must be finite (not NaN/inf) and strictly positive. Non-numeric or non-positive measurements indicate a broken run and are rejected so plots never contain garbage points.

Solutions

  1. Fix the offending numeric value in the CSV so it is finite and > 0
  2. Re-run the benchmark to regenerate valid measurements
  3. Validate upstream collector output before writing the CSV

Example fix

// before (CSV)
...,seconds=0,...
// after
...,seconds=12.5,...
Defensive patterns

Strategy: validation

Validate before calling

import math
def validate_positive(value):
    v = float(value)
    if not math.isfinite(v) or v <= 0:
        raise ValueError("measurements must be finite and positive")
    return v

Type guard

def is_positive_finite(value) -> bool:
    try:
        v = float(value)
    except (TypeError, ValueError):
        return False
    return math.isfinite(v) and v > 0

Try / catch

try:
    configuration, runs = read_runs(path, percentile)
except ValueError as e:
    print(f"bad measurement: {e}")

Prevention

When it happens

Trigger: A numeric column contains 0, a negative number, NaN, inf, or a non-numeric string that float() happens to parse (or the computed value like queries/seconds or peak_heap_bytes ends up non-positive).

Common situations: Missing/placeholder values like 0 or -1 in the CSV; division producing inf/nan from earlier validation gaps; corrupted or truncated measurement output.

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


AI-assisted analysis of tursodatabase/turso@8d4a589f8d (2026-09-20). Data as JSON: /api/errors/f195645f4651aba9. Report an issue: GitHub.

Appendix: source

Thrown at perf/fts/plot/plot-fts.py:147

        value = float(row["peak_heap_bytes"]) / (1024 * 1024)
    elif row["benchmark"] == "search":
        if not 0 < int(row["connections"]) <= queries or queries != int(row["requested_queries"]):
            raise ValueError("search results require at least one sample per connection and the requested query count")
        value = float(row[f"{percentile}_ms"])
    elif row["benchmark"] == "throughput":
        minimum = positive_number(row["min_seconds"])
        if seconds < minimum:
            raise ValueError("throughput results must meet a positive minimum duration")
        value = queries / seconds
    else:
        raise ValueError("unknown benchmark")
    return positive_number(value)


def positive_number(value):
    value = float(value)
    if not np.isfinite(value) or value <= 0:
        raise ValueError("measurements must be finite and positive")
    return value


def plot_sweep(configuration, points, output, relative=False):
    import matplotlib

    matplotlib.use("Agg")
    import matplotlib.pyplot as plt
    from matplotlib.ticker import FuncFormatter, MaxNLocator, NullLocator

    importlib.import_module("scienceplots")
    plt.style.use(["science", "no-latex"])
    fig, axes = plt.subplots(2, 3, figsize=(11, 8), dpi=300)
    connections = list(points)
    if relative and (configuration["benchmark"] == "memory" or ("sqlite", "wal") not in points[connections[0]]):
        raise ValueError("speedup plots require SQLite timing results")
    for index, (query, ax) in enumerate(zip(QUERIES, axes.flat)):
        table_rows = []

View on GitHub (pinned to 8d4a589f8d)