{"record":{"id":"09d284efce1f176e","repo":"RyanCodrai/turbovec","slug":"invalid-tq-shift-at-coord-i-v-must-be-finit","errorCode":null,"errorMessage":"invalid TQ+ shift at coord {i}: {v} (must be finite and |shift| <= {:e} at dim {})","messagePattern":"invalid TQ\\+ shift at coord (.+?): (.+?) \\(must be finite and \\|shift\\| <= (.+?) at dim (.+?)\\)","errorType":"validation","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"turbovec/src/io.rs","lineNumber":580,"sourceCode":"pub(crate) const MAX_VECTOR_SCALE: f32 = 1e22;\n\n/// Value-level calibration validation — THE rule, shared by every\n/// loader (v6 here, v7 in `io_v7`): the encoder only ever emits finite\n/// shifts and strictly-positive scales, so anything else is corruption\n/// or an attacker payload. Search divides by `tqplus_scale`, so a\n/// zero/negative/non-finite value — which a bare is_finite() check\n/// would not fully catch — silently turns every query's scores into\n/// NaN/Inf.\npub(crate) fn validate_calibration(\n    tqplus_shift: &[f32],\n    tqplus_scale: &[f32],\n) -> io::Result<()> {\n    if let Some((i, &v)) = tqplus_shift\n        .iter()\n        .enumerate()\n        .find(|(_, v)| !v.is_finite() || v.abs() > max_tqplus_shift(tqplus_shift.len()))\n    {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidData,\n            format!(\n                \"invalid TQ+ shift at coord {i}: {v} (must be finite and \\\n                 |shift| <= {:e} at dim {})\",\n                max_tqplus_shift(tqplus_shift.len()),\n                tqplus_shift.len()\n            ),\n        ));\n    }\n    if let Some((i, &v)) = tqplus_scale\n        .iter()\n        .enumerate()\n        .find(|(_, v)| !v.is_finite() || **v < min_tqplus_scale(tqplus_scale.len()))\n    {\n        return Err(io::Error::new(\n            io::ErrorKind::InvalidData,\n            format!(\n                \"invalid TQ+ scale at coord {i}: {v} (must be finite and \\","sourceCodeStart":562,"sourceCodeEnd":598,"githubUrl":"https://github.com/RyanCodrai/turbovec/blob/ccab9f325e6ce2a270a87daf01ae4e443bcf2d49/turbovec/src/io.rs#L562-L598","documentation":"validate_calibration rejects TQ+ calibration shift vectors containing non-finite values (NaN/Inf) or magnitudes exceeding max_tqplus_shift(dim) for the given dimension. The bound exists because the shift is applied per coordinate during search; unbounded shifts would destroy score ordering. The error pinpoints the offending coordinate index, value, bound, and dimension.","triggerScenarios":"Loading or saving a calibration (via the v7 image or calibrate API) whose tqplus_shift slice contains NaN, Inf, or a value whose absolute value exceeds the dimension-dependent limit max_tqplus_shift(len).","commonSituations":"Hand-editing calibration parameters; producing shifts from a numerically unstable training run; deserializing calibrations from another tool without range checks.","solutions":["Clamp each shift to the allowed bound max_tqplus_shift(dim) before saving/loading","Replace NaN/Inf entries with finite values or recompute the calibration","Check the calibration training pipeline for numerical overflow","Reduce per-coordinate shift magnitudes or rescale the embedding space"],"exampleFix":"// before\ncal.tqplus_shift = raw_shifts; // may contain 1e400\n// after\nlet lim = max_tqplus_shift(raw_shifts.len());\ncal.tqplus_shift = raw_shifts.iter().map(|&v| v.clamp(-lim, lim)).collect();","handlingStrategy":"validation","validationCode":"let lim = turbovec::max_tqplus_shift(shift.len());\nassert!(shift.iter().all(|&v| v.is_finite() && v.abs() <= lim),\n        \"TQ+ shift out of range (limit {lim:e})\");","typeGuard":"fn shift_valid(s: &[f64]) -> bool {\n    let lim = turbovec::max_tqplus_shift(s.len());\n    s.iter().all(|&v| v.is_finite() && v.abs() <= lim)\n}","tryCatchPattern":"match validate_calibration(&cal) {\n    Err(e) if e.to_string().contains(\"invalid TQ+ shift\") => {\n        eprintln!(\"calibration rejected: {e}; recomputing\");\n        cal.tqplus_shift = recompute_shifts();\n    }\n    other => other?,\n}","preventionTips":["Clamp shifts to max_tqplus_shift(dim) right after fitting","Assert finiteness of calibration arrays in unit tests","Sanity-check any calibration imported from external tools"],"tags":["validation","calibration","numeric-range"],"backgroundTag":"value-out-of-range","analyzedSha":"ccab9f325e6ce2a270a87daf01ae4e443bcf2d49","analyzedAt":"2026-09-06T08:39:18.516Z","contentChangedAt":"2026-09-06T08:39:18.516Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}