a-b-street/abstreet · error

The common roads on the first aren't consecutive, near

Error message

The common roads on the first aren't consecutive, near {:?}

What it means

After rotation, try_to_merge requires the common roads on the first perimeter to form one consecutive run at the end of the list. A gap was found (a non-common road inside what should be the shared tail), so the perimeters don't share a single contiguous boundary and the merge bails, naming the offending road side.

Solutions

  1. Skip this merge pair (use debug_failures=true to log and continue instead of failing hard).
  2. Inspect the road side named in the message to find the intervening geometry; adjust block formation or the skip set.
  3. Attempt merging with a different neighbor block instead.
Defensive patterns

Strategy: fallback

Try / catch

if let Err(e) = a.try_to_merge(map, b, &mut small_roads, /*debug_failures*/ true) {
    warn!("merge skipped: {}", e); // message names the offending road side
    continue;
}

Prevention

When it happens

Trigger: try_to_merge where, scanning self.roads in reverse over the last `common.len()` entries, an entry's road is not in `common` — the common roads are not consecutive even though the counts matched.

Common situations: Complex block shapes where the shared boundary is interrupted by another block touching in between; geometry produced by aggressive earlier merges; maps with irregular intersections.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13). Data as JSON: /api/errors/93e4976abff0d6ae. Report an issue: GitHub.

Appendix: source

Thrown at blockfinding/src/lib.rs:274

                self.restore_invariant();
                other.restore_invariant();
                self.roads.reverse();
                continue;
            }

            // Check if all of the common roads are at the end of each perimeter, so we can
            // "blindly" do this snipping. If this isn't true, then the overlapping portions are
            // split by non-overlapping roads. This happens when merging the two blocks would
            // result in a "hole."
            for id in self.roads.iter().rev().take(common.len()) {
                if !common.contains(&id.road) {
                    if debug_failures {
                        warn!(
                            "The common roads on the first aren't consecutive, near {:?}",
                            id
                        );
                    }
                    bail!(
                        "The common roads on the first aren't consecutive, near {:?}",
                        id
                    );
                }
            }
            for id in other.roads.iter().rev().take(common.len()) {
                if !common.contains(&id.road) {
                    if debug_failures {
                        warn!(
                            "The common roads on the second aren't consecutive, near {:?}",
                            id
                        );
                    }
                    bail!(
                        "The common roads on the first aren't consecutive, near {:?}",
                        id
                    );
                }

View on GitHub (pinned to 0964f29315)