a-b-street/abstreet · error

doesn't point to

Error message

{} doesn't point to {}

What it means

This constructor builds a DirectedRoadID pointing away from intersection i, choosing Fwd if i is the source endpoint and Back if it's the destination. Panics when i is not an endpoint of the road, so no valid direction exists.

Solutions

  1. Ensure i comes from road.src_i or road.dst_i (or other_endpt results) before constructing.
  2. Fix pathfinding adjacency so expansion only uses roads incident to the intersection.
  3. Refresh IDs if the map was reloaded or regenerated.

Example fix

// before
let dr = DirectedRoadID { road: r.id, dir: ??? };
// after
let dr = r.DirectedRoadID(i); // only after asserting r.src_i == i || r.dst_i == i
Defensive patterns

Strategy: type-guard

Type guard

fn directed_road_safe(road: &Road, i: IntersectionID) -> Option<DirectedRoadID> {
    if road.src_i == i { Some(DirectedRoadID { road: road.id, dir: Direction::Fwd }) }
    else if road.dst_i == i { Some(DirectedRoadID { road: road.id, dir: Direction::Back }) }
    else { None }
}

Prevention

When it happens

Trigger: Calling road.DirectedRoadID(i) (the constructor) with an IntersectionID that is neither road.src_i nor road.dst_i — e.g. from pathfinding expansion over wrong adjacency lists.

Common situations: Custom routing algorithms expanding directed roads from intersections; using intersection IDs from a different road after ID staleness.

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/22cd9dbb6a6ee793. Report an issue: GitHub.

Appendix: source

Thrown at map_model/src/objects/road.rs:545

    /// Many roads wind up with almost no length, due to their representation in OpenStreetMap. In
    /// reality, these segments are likely located within the interior of an intersection. This
    /// method uses a hardcoded threshold to detect these cases.
    pub fn is_extremely_short(&self) -> bool {
        self.length() < Distance::meters(2.0)
    }

    /// Get the DirectedRoadID pointing to the intersection. Panics if the intersection isn't an
    /// endpoint.
    pub fn directed_id_from(&self, i: IntersectionID) -> DirectedRoadID {
        DirectedRoadID {
            road: self.id,
            dir: if self.src_i == i {
                Direction::Fwd
            } else if self.dst_i == i {
                Direction::Back
            } else {
                panic!("{} doesn't point to {}", self.id, i);
            },
        }
    }

    /// Get the DirectedRoadID pointing from the intersection. Panics if the intersection isn't an
    /// endpoint.
    pub fn directed_id_to(&self, i: IntersectionID) -> DirectedRoadID {
        let mut id = self.directed_id_from(i);
        id.dir = id.dir.opposite();
        id
    }

    pub(crate) fn recreate_lanes(&mut self, lane_specs_ltr: Vec<LaneSpec>) {
        self.lanes.clear();

        let total_width = lane_specs_ltr.iter().map(|x| x.width).sum();

        let mut width_so_far = Distance::ZERO;

View on GitHub (pinned to 0964f29315)