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

  1. Regenerate or update the edits file against the current map so gtfs_id values match
  2. Verify you're loading edits into the same map they were created from
  3. Remove the stale ChangeRouteSchedule entry from the edits JSON
  4. Re-create the route-schedule edit in the GUI against the current map

Example fix

// before
let id = map.find_tr_by_gtfs(&gtfs_id).ok_or_else(|| anyhow!("can't find {}", gtfs_id))?;
// after
let id = map.find_tr_by_gtfs(&gtfs_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(&gtfs_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

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


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(&gtfs_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)