a-b-street/abstreet · error

Bad DistanceInterval

Error message

Bad DistanceInterval {} .. {}

What it means

DistanceInterval::new_driving validates that the driving interval runs forward along a lane: end must be >= start. Driving distances must be monotonic, so a reversed interval panics at construction instead of yielding a negative-length slice.

Solutions

  1. Use new_walking instead if the interval may be reversed (contraflow) by design
  2. Check that end is measured further along the same lane than start
  3. Clamp or swap the distances before constructing

Example fix

// before
let d = DistanceInterval::new_driving(far, near);
// after
let d = if far < near { DistanceInterval::new_driving(far, far.max(near)) } else { DistanceInterval::new_driving(near, far) };
Defensive patterns

Strategy: validation

Validate before calling

if end >= start { let d = DistanceInterval::new_driving(start, end); }

Type guard

fn valid_driving_interval(start: Distance, end: Distance) -> bool { end >= start }

Try / catch

let d = std::panic::catch_unwind(|| DistanceInterval::new_driving(start, end)).ok();

Prevention

When it happens

Trigger: Calling DistanceInterval::new_driving(start, end) with end < start, typically from mixed-up along-lane distances. Note new_walking deliberately permits start > end (contraflow), so only the driving constructor panics.

Common situations: Path-following code that computes start/end distances from wrong direction of traversal; agents routed the wrong way on one-way lanes; unit confusion between lane-length fractions and absolute distances.

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 a-b-street/abstreet@0964f29315 (2026-09-13). Data as JSON: /api/errors/b1a24d82951b4e61. Report an issue: GitHub.

Appendix: source

Thrown at sim/src/lib.rs:538

    pub fn percent_clamp_end(&self, t: Time) -> f64 {
        if t > self.end {
            return 1.0;
        }
        self.percent(t)
    }
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
pub(crate) struct DistanceInterval {
    // TODO Private fields
    pub start: Distance,
    pub end: Distance,
}

impl DistanceInterval {
    pub fn new_driving(start: Distance, end: Distance) -> DistanceInterval {
        if end < start {
            panic!("Bad DistanceInterval {} .. {}", start, end);
        }
        DistanceInterval { start, end }
    }

    pub fn new_walking(start: Distance, end: Distance) -> DistanceInterval {
        // start > end is fine, might be contraflow.
        DistanceInterval { start, end }
    }

    pub fn lerp(&self, x: f64) -> Distance {
        assert!((0.0..=1.0).contains(&x));
        self.start + x * (self.end - self.start)
    }

    pub fn length(&self) -> Distance {
        (self.end - self.start).abs()
    }
}

View on GitHub (pinned to 0964f29315)