{"record":{"id":"bbc386bef335a4a9","repo":"a-b-street/abstreet","slug":"this-change-had-no-effect","errorCode":null,"errorMessage":"This change had no effect.","messagePattern":"This change had no effect\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"map_model/src/objects/traffic_signals.rs","lineNumber":255,"sourceCode":"            }\n            // Ignoring crosswalks, do any of the turns come from a major road?\n            if stage\n                .protected_movements\n                .iter()\n                .any(|m| !m.crosswalk && highest_rank == rank_per_road[&m.from.road])\n            {\n                stage.stage_type = StageType::Fixed(major);\n            } else {\n                stage.stage_type = StageType::Fixed(minor);\n            }\n        }\n\n        if self.simple_cycle_duration() != major + minor {\n            bail!(\"This intersection didn't already group major/minor roads together.\");\n        }\n\n        if self == &orig {\n            bail!(\"This change had no effect.\");\n        }\n\n        Ok(())\n    }\n\n    pub fn missing_turns(&self, i: &Intersection) -> BTreeSet<MovementID> {\n        let mut missing: BTreeSet<MovementID> = i.movements.keys().cloned().collect();\n        for stage in &self.stages {\n            for m in &stage.protected_movements {\n                missing.remove(m);\n            }\n            for m in &stage.yield_movements {\n                missing.remove(m);\n            }\n        }\n        missing\n    }\n","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/a-b-street/abstreet/blob/0964f29315820c91b171b585eb51e300164e9197/map_model/src/objects/traffic_signals.rs#L237-L273","documentation":"At the end of adjust_major_minor_timing, if the transformed signal equals the original clone, the requested major/minor durations were identical to the existing timing — the call is a no-op, so the method bails to signal that nothing changed rather than reporting spurious success.","triggerScenarios":"Calling adjust_major_minor_timing with (major, minor) exactly equal to the current stage durations of the two stages.","commonSituations":"Batch retiming scripts re-applying the same values to already-tuned signals; idempotent retries where the first application already succeeded.","solutions":["Compare requested durations to current stage durations and skip the call if identical","Treat this bail as a benign no-op in batch tooling and continue","Only call the method when an actual timing change is intended","Collect which signals reported no-op and filter them from future runs"],"exampleFix":"// before\nsignal.adjust_major_minor_timing(major, minor, map)?;\n// after\nif signal.stages.iter().map(|s| s.stage_type.simple_duration()).collect::<Vec<_>>()\n    != vec![major, minor] {\n    signal.adjust_major_minor_timing(major, minor, map)?;\n} // otherwise it's already in the desired state","handlingStrategy":"validation","validationCode":"let current: Vec<Duration> = signal.stages.iter()\n    .map(|s| s.stage_type.simple_duration()).collect();\nif current == vec![major, minor] {\n    return Ok(()); // nothing to do\n}","typeGuard":"fn timing_would_change(signal: &TrafficSignal, major: Duration, minor: Duration) -> bool {\n    let d: Vec<Duration> = signal.stages.iter()\n        .map(|s| s.stage_type.simple_duration()).collect();\n    d != vec![major, minor]\n}","tryCatchPattern":"match signal.adjust_major_minor_timing(major, minor, map) {\n    Err(e) if e.to_string().contains(\"no effect\") => { /* benign no-op, continue */ }\n    other => other?,\n}","preventionTips":["Skip signals already at the target timing before batch retiming","Treat 'no effect' as idempotent success in retry loops","Record applied timings so repeat runs don't re-apply identical values"],"tags":["traffic-signals","no-op"],"backgroundTag":"invalid-argument-value","analyzedSha":"0964f29315820c91b171b585eb51e300164e9197","analyzedAt":"2026-09-13T18:02:03.421Z","contentChangedAt":"2026-09-13T18:02:03.421Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}