a-b-street/abstreet · error

Couldn't load edits

Error message

Couldn't load edits "{}": {}

What it means

When the `load` value points at an edits file, load_synchronously parses it with abstutil and applies it to the map. If the edits file cannot be deserialized (corrupt JSON, wrong schema, missing file surfaced as an error), the loader panics because continuing with an un-edited map would silently produce wrong simulation results.

Solutions

  1. Regenerate or fix the edits JSON so it deserializes and matches the current map schema
  2. Verify the path points to an existing edits file for THIS map (matching map version/name)
  3. Load the map and apply edits interactively in the UI, then re-save the edits

Example fix

// check before loading
if !abstutil::path_exists(&edits_path) {
    eprintln!("missing edits file {}", edits_path);
} else {
    flags.load_synchronously(&mut timer);
}
Defensive patterns

Strategy: validation

Validate before calling

if abstutil::path_exists(&edits_path) {
    match abstutil::read_json::<PermanentEdits>(&edits_path) {
        Ok(_) => flags.load_synchronously(&mut timer),
        Err(e) => eprintln!("bad edits: {}", e),
    }
}

Try / catch

let result = std::panic::catch_unwind(|| flags.load_synchronously(&mut timer));
if result.is_err() { eprintln!("failed to load edits"); }

Prevention

When it happens

Trigger: Passing a path to a permanent edits file in `load` where abstutil::read fails: malformed JSON, edits produced by an older/newer schema version, wrong path, or the file failing must_apply_edits validation.

Common situations: Hand-edited or partially written edits JSON; edits saved from a different map version than the map being loaded; typos in the edits file path; repo data regenerated between versions.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at sim/src/make/load.rs:98

        let mut opts = self.opts.clone();

        if self.load.starts_with(&abstio::path_player("saves/")) {
            info!("Resuming from {}", self.load);

            let sim: Sim = abstio::must_read_object(self.load.clone(), timer);

            let mut map = Map::load_synchronously(sim.map_name.path(), timer);
            match MapEdits::load_from_file(
                &map,
                abstio::path_edits(map.get_name(), &sim.edits_name),
                timer,
            ) {
                Ok(edits) => {
                    map.must_apply_edits(edits, timer);
                    map.recalculate_pathfinding_after_edits(timer);
                }
                Err(err) => {
                    panic!("Couldn't load edits \"{}\": {}", sim.edits_name, err);
                }
            }

            (map, sim, rng)
        } else if self.load.contains("/scenarios/") {
            info!("Seeding the simulation from scenario {}", self.load);

            let mut scenario: Scenario = abstio::must_read_object(self.load.clone(), timer);

            let map = Map::load_synchronously(scenario.map_name.path(), timer);

            for m in &self.scenario_modifiers {
                scenario = m.apply(&map, scenario, &mut rng);
            }

            if opts.run_name == "unnamed" {
                opts.run_name = scenario.scenario_name.clone();
            }

View on GitHub (pinned to 0964f29315)