{"record":{"id":"f195645f4651aba9","repo":"tursodatabase/turso","slug":"measurements-must-be-finite-and-positive","errorCode":null,"errorMessage":"measurements must be finite and positive","messagePattern":"measurements must be finite and positive","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"perf/fts/plot/plot-fts.py","lineNumber":147,"sourceCode":"        value = float(row[\"peak_heap_bytes\"]) / (1024 * 1024)\n    elif row[\"benchmark\"] == \"search\":\n        if not 0 < int(row[\"connections\"]) <= queries or queries != int(row[\"requested_queries\"]):\n            raise ValueError(\"search results require at least one sample per connection and the requested query count\")\n        value = float(row[f\"{percentile}_ms\"])\n    elif row[\"benchmark\"] == \"throughput\":\n        minimum = positive_number(row[\"min_seconds\"])\n        if seconds < minimum:\n            raise ValueError(\"throughput results must meet a positive minimum duration\")\n        value = queries / seconds\n    else:\n        raise ValueError(\"unknown benchmark\")\n    return positive_number(value)\n\n\ndef positive_number(value):\n    value = float(value)\n    if not np.isfinite(value) or value <= 0:\n        raise ValueError(\"measurements must be finite and positive\")\n    return value\n\n\ndef plot_sweep(configuration, points, output, relative=False):\n    import matplotlib\n\n    matplotlib.use(\"Agg\")\n    import matplotlib.pyplot as plt\n    from matplotlib.ticker import FuncFormatter, MaxNLocator, NullLocator\n\n    importlib.import_module(\"scienceplots\")\n    plt.style.use([\"science\", \"no-latex\"])\n    fig, axes = plt.subplots(2, 3, figsize=(11, 8), dpi=300)\n    connections = list(points)\n    if relative and (configuration[\"benchmark\"] == \"memory\" or (\"sqlite\", \"wal\") not in points[connections[0]]):\n        raise ValueError(\"speedup plots require SQLite timing results\")\n    for index, (query, ax) in enumerate(zip(QUERIES, axes.flat)):\n        table_rows = []","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/tursodatabase/turso/blob/8d4a589f8d13ac184700d2a8f724f27e1995be3b/perf/fts/plot/plot-fts.py#L129-L165","documentation":"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.","triggerScenarios":"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).","commonSituations":"Missing/placeholder values like 0 or -1 in the CSV; division producing inf/nan from earlier validation gaps; corrupted or truncated measurement output.","solutions":["Fix the offending numeric value in the CSV so it is finite and > 0","Re-run the benchmark to regenerate valid measurements","Validate upstream collector output before writing the CSV"],"exampleFix":"// before (CSV)\n...,seconds=0,...\n// after\n...,seconds=12.5,...","handlingStrategy":"validation","validationCode":"import math\ndef validate_positive(value):\n    v = float(value)\n    if not math.isfinite(v) or v <= 0:\n        raise ValueError(\"measurements must be finite and positive\")\n    return v","typeGuard":"def is_positive_finite(value) -> bool:\n    try:\n        v = float(value)\n    except (TypeError, ValueError):\n        return False\n    return math.isfinite(v) and v > 0","tryCatchPattern":"try:\n    configuration, runs = read_runs(path, percentile)\nexcept ValueError as e:\n    print(f\"bad measurement: {e}\")","preventionTips":["Reject 0/negative/NaN placeholders at collection time","Validate CSV numerics before plotting","Check harness output for truncation or corruption that yields invalid numbers"],"tags":["python","benchmark","numeric-validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"8d4a589f8d13ac184700d2a8f724f27e1995be3b","analyzedAt":"2026-09-20T13:18:14.658Z","contentChangedAt":"2026-09-20T13:18:14.658Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}