{"record":{"id":"9925722aabd5b03c","repo":"a-b-street/abstreet","slug":"speed-limit-has-changed","errorCode":null,"errorMessage":"{:?} speed limit has changed","messagePattern":"(.+?) speed limit has changed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"map_model/src/edits/compat.rs","lineNumber":249,"sourceCode":"            let dst_i = map.find_i_by_osm_id(obj.dst_i)?;\n            let road = modified.entry(r).or_insert_with(|| map.get_r_edit(r));\n            let edits_dir = if dst_i == map.get_r(r).dst_i {\n                Direction::Fwd\n            } else if dst_i == map.get_r(r).src_i {\n                Direction::Back\n            } else {\n                bail!(\"{:?}'s road doesn't point to dst_i at all\", obj);\n            };\n            if road.lanes_ltr[idx].dir == edits_dir {\n                bail!(\"{:?}'s road already points to dst_i\", obj);\n            }\n            road.lanes_ltr[idx].dir = edits_dir;\n        } else if let Some(obj) = cmd.remove(\"ChangeSpeedLimit\") {\n            let obj: ChangeSpeedLimit = serde_json::from_value(obj).unwrap();\n            let r = map.find_r_by_osm_id(obj.id)?;\n            let road = modified.entry(r).or_insert_with(|| map.get_r_edit(r));\n            if road.speed_limit != obj.old {\n                bail!(\"{:?} speed limit has changed\", obj);\n            }\n            road.speed_limit = obj.new;\n        } else if let Some(obj) = cmd.remove(\"ChangeAccessRestrictions\") {\n            let obj: ChangeAccessRestrictions = serde_json::from_value(obj).unwrap();\n            let r = map.find_r_by_osm_id(obj.id)?;\n            let road = modified.entry(r).or_insert_with(|| map.get_r_edit(r));\n            if road.access_restrictions != obj.old {\n                bail!(\"{:?} access restrictions have changed\", obj);\n            }\n            road.access_restrictions = obj.new.clone();\n        } else {\n            commands.push(orig);\n        }\n    }\n\n    for (r, new) in modified {\n        let old = map.get_r_edit(r);\n        commands","sourceCodeStart":231,"sourceCodeEnd":267,"githubUrl":"https://github.com/a-b-street/abstreet/blob/0964f29315820c91b171b585eb51e300164e9197/map_model/src/edits/compat.rs#L231-L267","documentation":"While upgrading old edits, a ChangeSpeedLimit command records the previous speed limit (obj.old). The upgrade verifies it still matches the road's current speed_limit; if not, the edit was based on a state that no longer exists, so it aborts rather than applying a change with the wrong baseline.","triggerScenarios":"Loading a saved edit whose ChangeSpeedLimit.old differs from road.speed_limit in the current map — e.g. the basemap was regenerated (different OSM-derived defaults) or the limit was already changed.","commonSituations":"Re-importing a map after OSM data updates changed default speed limits; loading edits saved against an older map build; applying an edit file twice.","solutions":["Update the command's `old` field in the edit JSON to the road's current speed limit.","Remove the ChangeSpeedLimit command and re-apply the speed limit change in the app.","Regenerate the map so the speed limit matches the edit's recorded old value."],"exampleFix":"// before (edit JSON)\n{\"ChangeSpeedLimit\": {\"id\": 42, \"old\": 30.0, \"new\": 20.0}}\n// after: update `old` to the current limit\n{\"ChangeSpeedLimit\": {\"id\": 42, \"old\": 25.0, \"new\": 20.0}}","handlingStrategy":"validation","validationCode":"// confirm the recorded old speed limit matches the current road\nlet r = map.find_r_by_osm_id(cmd.id)?;\nif map.get_r_edit(r).speed_limit != cmd.old { /* update `old` or drop cmd */ }","typeGuard":null,"tryCatchPattern":"match Edits::load_from_bytes(map, bytes) {\n    Ok(e) => Ok(e),\n    Err(err) if err.to_string().contains(\"speed limit has changed\") => {\n        Err(anyhow!(\"edit baseline stale: {}\", err))\n    }\n    Err(err) => Err(err),\n}","preventionTips":["After OSM re-import, refresh the `old` fields in saved edits or re-create them.","Expect default speed limits to change between map builds; diff before replaying.","Keep edits tied to a specific map version."],"tags":["edits","compatibility","state-mismatch"],"backgroundTag":"schema-validation-failed","analyzedSha":"0964f29315820c91b171b585eb51e300164e9197","analyzedAt":"2026-09-13T18:02:03.421Z","contentChangedAt":"2026-09-13T18:02:03.421Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}