a-b-street/abstreet · error
doesn't contain both and
Error message
{} doesn't contain both {} and {} What it means
get_lanes_between walks the road's ordered child lanes and collects all lanes between lanes l1 and l2 (inclusive by id match). Panics when the scan finishes without having matched both lane IDs, meaning at least one lane isn't a child of this road.
Solutions
- Confirm both l1 and l2 are children of self.id before calling (scan children lists).
- Re-resolve the lane pair from current map state (e.g. by lane type and offset) instead of cached IDs.
- Update or discard stale edits JSON that references regenerated lane IDs.
Example fix
// before
let lanes = road.get_lanes_between(a, b);
// after
let kids: Vec<_> = road.children(Direction::Fwd).iter().chain(road.children(Direction::Back).iter()).map(|(l, _)| *l).collect();
if !kids.contains(&a) || !kids.contains(&b) { anyhow::bail!("lanes not on {}", road.id); }
let lanes = road.get_lanes_between(a, b); Defensive patterns
Strategy: validation
Validate before calling
// verify both lanes belong to the road first
let kids: Vec<LaneID> = road.children(Direction::Fwd).iter().chain(road.children(Direction::Back).iter()).map(|(l, _)| *l).collect();
if !kids.contains(&l1) || !kids.contains(&l2) { return Err(anyhow!("lanes not on road {}", road.id)); } Prevention
- Do not persist lane IDs across map edits; recompute by lane type/offset
- Validate edits JSON lane references against the current map on load
- Keep lane-range helpers total (return Option/Result)
When it happens
Trigger: Calling road.get_lanes_between(l1, l2) where either lane belongs to a different road, or IDs are stale relative to the current map (edits applied, lanes merged/deleted).
Common situations: Edit code computing the range of lanes to modify (e.g. lane-type changes between two driving lanes); using persisted lane IDs from an older map version.
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
- isn't an endpoint of
- must_get_sidewalk broken by
- doesn't contain
- Some IndividTrip wasn't associated with a Person?!
- ( ) is a border, but is connected to >1 road
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/7ec1091007fdb6e2.
Report an issue: GitHub.
Appendix: source
Thrown at map_model/src/objects/road.rs:617
});
}
}
/// Returns all lanes located between l1 and l2, exclusive.
pub fn get_lanes_between(&self, l1: LaneID, l2: LaneID) -> Vec<LaneID> {
let mut results = Vec::new();
let mut found_start = false;
for l in &self.lanes {
if found_start {
if l.id == l1 || l.id == l2 {
return results;
}
results.push(l.id);
} else if l.id == l1 || l.id == l2 {
found_start = true;
}
}
panic!("{} doesn't contain both {} and {}", self.id, l1, l2);
}
/// A simple classification of if the directed road is stressful or not for cycling. Arterial
/// roads without a bike lane match this. Why arterial, instead of looking at speed limits?
/// Even on arterial roads with official speed limits lowered, in practice vehicles still
/// travel at the speed suggested by the design of the road.
// TODO Should elevation matter or not? Flat high-speed roads are still terrifying, but there's
// something about slogging up (or flying down!) a pothole-filled road inches from cars.
pub fn high_stress_for_bikes(&self, map: &Map, dir: Direction) -> bool {
let mut bike_lanes = false;
let mut can_use = false;
// Can a bike even use it, or is it a highway?
for l in &self.lanes {
if l.lane_type == LaneType::Biking && l.dir == dir {
bike_lanes = true;
}
if PathConstraints::Bike.can_use(l, map) {
can_use = true;View on GitHub (pinned to 0964f29315)