RyanCodrai/turbovec · error · io::Error

invalid TQ+ shift at coord {i}: {v} (must be finite and |shi

Error message

invalid TQ+ shift at coord {i}: {v} (must be finite and |shift| <= {:e} at dim {})

What it means

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.

Source

Thrown at turbovec/src/io.rs:580

pub(crate) const MAX_VECTOR_SCALE: f32 = 1e22;

/// Value-level calibration validation — THE rule, shared by every
/// loader (v6 here, v7 in `io_v7`): the encoder only ever emits finite
/// shifts and strictly-positive scales, so anything else is corruption
/// or an attacker payload. Search divides by `tqplus_scale`, so a
/// zero/negative/non-finite value — which a bare is_finite() check
/// would not fully catch — silently turns every query's scores into
/// NaN/Inf.
pub(crate) fn validate_calibration(
    tqplus_shift: &[f32],
    tqplus_scale: &[f32],
) -> io::Result<()> {
    if let Some((i, &v)) = tqplus_shift
        .iter()
        .enumerate()
        .find(|(_, v)| !v.is_finite() || v.abs() > max_tqplus_shift(tqplus_shift.len()))
    {
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            format!(
                "invalid TQ+ shift at coord {i}: {v} (must be finite and \
                 |shift| <= {:e} at dim {})",
                max_tqplus_shift(tqplus_shift.len()),
                tqplus_shift.len()
            ),
        ));
    }
    if let Some((i, &v)) = tqplus_scale
        .iter()
        .enumerate()
        .find(|(_, v)| !v.is_finite() || **v < min_tqplus_scale(tqplus_scale.len()))
    {
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            format!(
                "invalid TQ+ scale at coord {i}: {v} (must be finite and \

View on GitHub (pinned to ccab9f325e)

Solutions

  1. Clamp each shift to the allowed bound max_tqplus_shift(dim) before saving/loading
  2. Replace NaN/Inf entries with finite values or recompute the calibration
  3. Check the calibration training pipeline for numerical overflow
  4. Reduce per-coordinate shift magnitudes or rescale the embedding space

Example fix

// before
cal.tqplus_shift = raw_shifts; // may contain 1e400
// after
let lim = max_tqplus_shift(raw_shifts.len());
cal.tqplus_shift = raw_shifts.iter().map(|&v| v.clamp(-lim, lim)).collect();
Defensive patterns

Strategy: validation

Validate before calling

let lim = turbovec::max_tqplus_shift(shift.len());
assert!(shift.iter().all(|&v| v.is_finite() && v.abs() <= lim),
        "TQ+ shift out of range (limit {lim:e})");

Type guard

fn shift_valid(s: &[f64]) -> bool {
    let lim = turbovec::max_tqplus_shift(s.len());
    s.iter().all(|&v| v.is_finite() && v.abs() <= lim)
}

Try / catch

match validate_calibration(&cal) {
    Err(e) if e.to_string().contains("invalid TQ+ shift") => {
        eprintln!("calibration rejected: {e}; recomputing");
        cal.tqplus_shift = recompute_shifts();
    }
    other => other?,
}

Prevention

When it happens

Trigger: 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).

Common situations: Hand-editing calibration parameters; producing shifts from a numerically unstable training run; deserializing calibrations from another tool without range checks.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of RyanCodrai/turbovec@ccab9f325e (2026-09-06). Data as JSON: /api/errors/09d284efce1f176e. Report an issue: GitHub.