a-b-street/abstreet · error

isn't an endpoint of

Error message

{} isn't an endpoint of {}

What it means

Lane::endpoint returns the first or last point of the lane depending on which intersection is requested. Panics when the given IntersectionID is neither the lane's source nor destination intersection, i.e. the lane does not touch that intersection.

Solutions

  1. Verify the intersection is an endpoint: check lane.src_i or lane.dst_i before calling endpoint.
  2. Use lane.src_i or lane.dst_i directly instead of an assumed intersection.
  3. Do not persist LaneID/IntersectionID across map reloads; look them up by stable identifiers each time.
  4. Check caller logic (crosswalk generation, edits) that pairs lanes with intersections.

Example fix

// before
let pt = lane.endpoint(some_i);
// after
assert!(lane.src_i == some_i || lane.dst_i == some_i, "lane {} not at {}", lane.id, some_i);
let pt = lane.endpoint(some_i);
Defensive patterns

Strategy: type-guard

Type guard

fn lane_endpoint_ok(lane: &Lane, i: IntersectionID) -> Option<Pt2D> {
    if i == lane.src_i { Some(lane.first_pt()) }
    else if i == lane.dst_i { Some(lane.last_pt()) }
    else { None }
}

Prevention

When it happens

Trigger: Calling lane.endpoint(i) with an IntersectionID that is not lane.src_i or lane.dst_i — e.g. passing the wrong intersection from a turn-building loop or using a stale ID after edits/regeneration.

Common situations: Crosswalk or shared-sidewalk-corner construction (make_crosswalk, make_shared_sidewalk_corner) iterating wrong lane sets; using lane IDs from an old map after re-import, since IDs are not stable.

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/444ee56813235324. Report an issue: GitHub.

Appendix: source

Thrown at map_model/src/objects/lane.rs:114

        self.lane_center_pts.first_pt()
    }
    pub fn last_pt(&self) -> Pt2D {
        self.lane_center_pts.last_pt()
    }
    pub fn first_line(&self) -> Line {
        self.lane_center_pts.first_line()
    }
    pub fn last_line(&self) -> Line {
        self.lane_center_pts.last_line()
    }

    pub fn endpoint(&self, i: IntersectionID) -> Pt2D {
        if i == self.src_i {
            self.first_pt()
        } else if i == self.dst_i {
            self.last_pt()
        } else {
            panic!("{} isn't an endpoint of {}", i, self.id);
        }
    }

    /// pt2 will be endpoint
    pub fn end_line(&self, i: IntersectionID) -> Line {
        if i == self.src_i {
            self.first_line().reversed()
        } else if i == self.dst_i {
            self.last_line()
        } else {
            panic!("{} isn't an endpoint of {}", i, self.id);
        }
    }

    pub fn dist_along_of_point(&self, pt: Pt2D) -> Option<Distance> {
        self.lane_center_pts
            .dist_along_of_point(pt)
            .map(|(dist, _)| dist)

View on GitHub (pinned to 0964f29315)