{"record":{"id":"df4168be64794d5d","repo":"ppy/osu","slug":"cannot-update-a-scale-operation-without-calling-be","errorCode":null,"errorMessage":"Cannot Update a scale operation without calling Begin first!","messagePattern":"Cannot Update a scale operation without calling Begin first!","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"osu.Game.Rulesets.Osu/Edit/OsuSelectionScaleHandler.cs","lineNumber":103,"sourceCode":"        public override void Begin()\r\n        {\r\n            if (OperationInProgress.Value)\r\n                throw new InvalidOperationException($\"Cannot {nameof(Begin)} a scale operation while another is in progress!\");\r\n\r\n            base.Begin();\r\n\r\n            changeHandler?.BeginChange();\r\n\r\n            objectsInScale = selectedMovableObjects.ToDictionary(ho => ho, ho => new OriginalHitObjectState(ho));\r\n            OriginalSurroundingQuad = GeometryUtils.GetSurroundingQuad(objectsInScale.Keys);\r\n            originalConvexHull = GeometryUtils.GetConvexHull(objectsInScale.Keys);\r\n            defaultOrigin = GeometryUtils.MinimumEnclosingCircle(originalConvexHull).Item1;\r\n        }\r\n\r\n        public override void Update(Vector2 scale, Vector2? origin = null, Axes adjustAxis = Axes.Both, float axisRotation = 0)\r\n        {\r\n            if (!OperationInProgress.Value)\r\n                throw new InvalidOperationException($\"Cannot {nameof(Update)} a scale operation without calling {nameof(Begin)} first!\");\r\n\r\n            Debug.Assert(objectsInScale != null && defaultOrigin != null && OriginalSurroundingQuad != null);\r\n\r\n            Vector2 actualOrigin = origin ?? defaultOrigin.Value;\r\n            scale = clampScaleToAdjustAxis(scale, adjustAxis);\r\n\r\n            // for the time being, allow resizing of slider paths only if the slider is\r\n            // the only hit object selected. with a group selection, it's likely the user\r\n            // is not looking to change the duration of the slider but expand the whole pattern.\r\n            if (objectsInScale.Count == 1 && objectsInScale.First().Key is Slider slider)\r\n            {\r\n                scaleSlider(slider, scale, actualOrigin, objectsInScale[slider], axisRotation);\r\n            }\r\n            else\r\n            {\r\n                scale = ClampScaleToPlayfieldBounds(scale, actualOrigin, adjustAxis, axisRotation);\r\n\r\n                foreach (var (ho, originalState) in objectsInScale)\r","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/ppy/osu/blob/d9c73e12adff2feaae4a3e158d36fe5883faf6ca/osu.Game.Rulesets.Osu/Edit/OsuSelectionScaleHandler.cs#L85-L121","documentation":"OsuSelectionScaleHandler.Update() applies a scale delta using objectsInScale, defaultOrigin, and OriginalSurroundingQuad, which are populated by Begin(). Without Begin, these are null. The guard throws before the Debug.Assert on nulls would fire.","triggerScenarios":"Calling Update(scale, origin, adjustAxis, axisRotation) before Begin() has been called.","commonSituations":"Input event ordering issues where the scale delta handler runs before initialization; state desync between the UI scale control and the handler's OperationInProgress.","solutions":["Ensure Begin() is called before any Update() in the scale lifecycle.","Guard Update calls behind an OperationInProgress.Value check."],"exampleFix":"// before\nscaleHandler.Update(deltaScale); // called before Begin\n\n// after\nif (scaleHandler.OperationInProgress.Value)\n    scaleHandler.Update(deltaScale);","handlingStrategy":"validation","validationCode":"// Guard Update against calls before Begin\nif (scaleHandler.OperationInProgress.Value)\n    scaleHandler.Update(deltaScale, origin, adjustAxis, axisRotation);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Route all Update calls through an OperationInProgress.Value guard.","Ensure event subscriptions are cleared on Commit to prevent stale callbacks."],"tags":["editor","osu-ruleset","selection","state-machine","scaling"],"backgroundTag":null,"analyzedSha":"d9c73e12adff2feaae4a3e158d36fe5883faf6ca","analyzedAt":"2026-08-13T14:12:54.015Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}