{"record":{"id":"87bde2596cdd2e3b","repo":"stride3d/stride","slug":"the-offset-must-be-either-1-0-or-1","errorCode":null,"errorMessage":"The offset must be either -1, 0 or 1","messagePattern":"The offset must be either -1, 0 or 1","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"sources/editor/Stride.Assets.Presentation/AssetEditors/SpriteEditor/ViewModels/SpriteSheetEditorViewModel.cs","lineNumber":371,"sourceCode":"            SelectedSprites.Clear();\n            SelectedSprites.AddRange(imagesToSelect.Select(FindViewModel));\n        }\n\n        private void SelectNextSprite(int offset)\n        {\n            if (SelectedSprites.Count == 1)\n            {\n                var index = Sprites.IndexOf(SelectedSprites.Cast<SpriteInfoViewModel>().First());\n                index = (Sprites.Count + index + offset) % Sprites.Count;\n                SelectedSprites.Clear();\n                SelectedSprites.Add(Sprites[index]);\n            }\n        }\n\n        private void MoveImage(int offset)\n        {\n            if (offset < -1 || offset > 1)\n                throw new ArgumentException(\"The offset must be either -1, 0 or 1\");\n\n            var imagesToMove = new List<SpriteInfoViewModel>(SelectedSprites.Cast<SpriteInfoViewModel>());\n            var toReselect = imagesToMove.Select(sivm => sivm.GetSpriteInfo()).ToList();\n            foreach (var selectedImage in SelectedSprites.Cast<SpriteInfoViewModel>().OrderBy(x => x.Index * -offset))\n            {\n                if (selectedImage.Index + offset < 0 || selectedImage.Index + offset >= Sprites.Count)\n                {\n                    imagesToMove.Remove(selectedImage);\n                    continue;\n                }\n                var targetImage = Sprites[selectedImage.Index + offset];\n                if (SelectedSprites.Contains(targetImage) && !imagesToMove.Contains(targetImage))\n                {\n                    imagesToMove.Remove(selectedImage);\n                }\n            }\n            if (imagesToMove.Count > 0)\n            {","sourceCodeStart":353,"sourceCodeEnd":389,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/editor/Stride.Assets.Presentation/AssetEditors/SpriteEditor/ViewModels/SpriteSheetEditorViewModel.cs#L353-L389","documentation":"MoveImage in the sprite sheet editor moves selected sprites by exactly one slot per call; it throws ArgumentException when the offset is outside the -1..1 range. The offset shifts each selected sprite's index, and larger jumps were intentionally not implemented.","triggerScenarios":"Calling MoveImage(2), MoveImage(-2), or any offset with |offset| > 1, directly or via a UI command/binding that passes a computed step size larger than one.","commonSituations":"Binding keyboard shortcuts or toolbar commands that pass a multi-slot displacement, programmatically moving sprites several positions at once instead of iterating.","solutions":["Pass only -1, 0 or 1; loop the call N times to move N positions.","Clamp the offset before calling: Math.Max(-1, Math.Min(1, offset)).","Change the caller to issue one-step moves per iteration.","If larger jumps are needed, extend MoveImage to compute an absolute target index instead of a limited delta."],"exampleFix":"// before\nspriteSheetEditorViewModel.MoveImage(3);\n// after\nfor (int i = 0; i < 3; i++)\n    spriteSheetEditorViewModel.MoveImage(1);\n","handlingStrategy":"validation","validationCode":"if (offset < -1 || offset > 1) throw new ArgumentOutOfRangeException(nameof(offset), offset, \"Offset must be -1, 0 or 1\");\nspriteSheetEditorViewModel.MoveImage(offset);","typeGuard":"bool IsSingleStepOffset(int offset) => offset is >= -1 and <= 1;","tryCatchPattern":"try { vm.MoveImage(offset); }\ncatch (ArgumentException ex) { // clamp and retry once\n    vm.MoveImage(Math.Sign(offset));\n}","preventionTips":["Only pass -1, 0 or 1; loop for multi-slot moves.","Clamp or Math.Sign the desired displacement before calling.","Validate command parameters at the UI binding layer.","Never wire raw step multipliers into MoveImage."],"tags":["csharp","stride","sprite-editor","argument-validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}