a-b-street/abstreet · error · anyhow::Error
can't find
Error message
can't find {} What it means
PermanentEditCmd::into_cmd converts a persisted, permanent edit into an EditCmd bound to a live Map. For ChangeRouteSchedule it resolves the GTFS route ID via map.find_tr_by_gtfs; if the map contains no matching transit route it errs with anyhow!("can't find {}"). This catches edits made against a different/incompatible map.
Solutions
- Regenerate or update the edits file against the current map so gtfs_id values match
- Verify you're loading edits into the same map they were created from
- Remove the stale ChangeRouteSchedule entry from the edits JSON
- Re-create the route-schedule edit in the GUI against the current map
Example fix
// before
let id = map.find_tr_by_gtfs(>fs_id).ok_or_else(|| anyhow!("can't find {}", gtfs_id))?;
// after
let id = map.find_tr_by_gtfs(>fs_id)
.with_context(|| format!("route {} not in this map; edits file may be stale — regenerate it", gtfs_id))?; Defensive patterns
Strategy: validation
Validate before calling
// before applying edits
if map.find_tr_by_gtfs(>fs_id).is_none() {
anyhow::bail!("edit references transit route {} absent from this map", gtfs_id);
} Try / catch
match perm.into_cmd(&map) {
Ok(cmd) => apply(cmd),
Err(e) if e.to_string().starts_with("can't find") => prompt_stale_edits(e),
Err(e) => return Err(e),
} Prevention
- Only apply edits files created from the same map version
- Regenerate edits after map re-imports or GTFS feed updates
- Store a map name/hash in the edits file and verify it before conversion
When it happens
Trigger: Loading a permanent edit JSON whose ChangeRouteSchedule references a gtfs_id not present in the current map — map regenerated, GTFS feed changed, or edit applied to the wrong map file.
Common situations: Applying saved edits after a map re-import with different route IDs; switching between cities/maps with the same edits file; GTFS feed updates removing or renumbering routes.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- Two consecutive stops are on the same road, but they travel…
- Transit route will warp from
- No transit route from
- isn't a traffic signal
- lane type has changed
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/7b62973ef65a21c1.
Report an issue: GitHub.
Appendix: source
Thrown at map_model/src/edits/perma.rs:146
}
Ok(EditCmd::ChangeRoad { r: id, new, old })
}
PermanentEditCmd::ChangeIntersection { i, new, old } => {
let id = map.find_i_by_osm_id(i)?;
Ok(EditCmd::ChangeIntersection {
i: id,
new: new
.with_permanent(id, map)
.with_context(|| format!("new ChangeIntersection of {} invalid", i))?,
old: old
.with_permanent(id, map)
.with_context(|| format!("old ChangeIntersection of {} invalid", i))?,
})
}
PermanentEditCmd::ChangeRouteSchedule { gtfs_id, old, new } => {
let id = map
.find_tr_by_gtfs(>fs_id)
.ok_or_else(|| anyhow!("can't find {}", gtfs_id))?;
Ok(EditCmd::ChangeRouteSchedule { id, old, new })
}
}
}
}
impl MapEdits {
/// Encode the edits in a permanent format, referring to more-stable OSM IDs.
pub fn to_permanent(&self, map: &Map) -> PermanentMapEdits {
PermanentMapEdits {
map_name: map.get_name().clone(),
edits_name: self.edits_name.clone(),
// Increase this every time there's a schema change
version: 13,
proposal_description: self.proposal_description.clone(),
proposal_link: self.proposal_link.clone(),
commands: self.commands.iter().map(|cmd| cmd.to_perma(map)).collect(),
}View on GitHub (pinned to 0964f29315)