{"record":{"id":"16fbd3f4d0e876d6","repo":"ppy/osu","slug":"unsupported-grid-type","errorCode":null,"errorMessage":"Unsupported grid type.","messagePattern":"Unsupported grid type\\.","errorType":"exception","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs","lineNumber":171,"sourceCode":"                case PositionSnapGridType.Triangle:\r\n                    var triangularPositionSnapGrid = new TriangularPositionSnapGrid();\r\n\r\n                    triangularPositionSnapGrid.Spacing.BindTo(OsuGridToolboxGroup.GridLineSpacing);\r\n                    triangularPositionSnapGrid.GridLineRotation.BindTo(OsuGridToolboxGroup.GridLinesRotation);\r\n\r\n                    positionSnapGrid = triangularPositionSnapGrid;\r\n                    break;\r\n\r\n                case PositionSnapGridType.Circle:\r\n                    var circularPositionSnapGrid = new CircularPositionSnapGrid();\r\n\r\n                    circularPositionSnapGrid.Spacing.BindTo(OsuGridToolboxGroup.GridLineSpacing);\r\n\r\n                    positionSnapGrid = circularPositionSnapGrid;\r\n                    break;\r\n\r\n                default:\r\n                    throw new ArgumentOutOfRangeException(nameof(OsuGridToolboxGroup.GridType), OsuGridToolboxGroup.GridType, \"Unsupported grid type.\");\r\n            }\r\n\r\n            // Bind the start position to the toolbox sliders.\r\n            positionSnapGrid.StartPosition.BindTo(OsuGridToolboxGroup.StartPosition);\r\n\r\n            positionSnapGrid.RelativeSizeAxes = Axes.Both;\r\n            LayerBelowRuleset.Add(positionSnapGrid);\r\n        }\r\n\r\n        protected override ComposeBlueprintContainer CreateBlueprintContainer()\r\n            => new OsuBlueprintContainer(this);\r\n\r\n        public override string ConvertSelectionToString()\r\n            => string.Join(',', selectedHitObjects.Cast<OsuHitObject>().OrderBy(h => h.StartTime)\r\n                                                  .Select(h => (h.IndexInCurrentCombo + 1).ToString(CultureInfo.InvariantCulture)));\r\n\r\n        // 1,2,3,4 ...\r\n        private static readonly Regex selection_regex = new Regex(@\"^\\d+(,\\d+)*$\", RegexOptions.Compiled);\r","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/ppy/osu/blob/d9c73e12adff2feaae4a3e158d36fe5883faf6ca/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs#L153-L189","documentation":"OsuHitObjectComposer.BuildPositionSnapGrid() instantiates a PositionSnapGrid subclass based on the selected PositionSnapGridType (Triangle, Square/Symmetric, Circle). The default case throws ArgumentOutOfRangeException for any enum value not covered, ensuring the editor never silently falls through to a null grid.","triggerScenarios":"A new PositionSnapGridType enum member is added without a corresponding case in the switch, and the user selects that grid type in the editor toolbox.","commonSituations":"Extending the osu! editor with a new snapping grid type but forgetting to implement the PositionSnapGrid instantiation; deserialization of a grid type value from a map/skin config that is outside the known set.","solutions":["Add a case for the new PositionSnapGridType value that instantiates the correct PositionSnapGrid subclass and binds its properties.","If the enum is data-driven, validate the value against the known set before assigning it to OsuGridToolboxGroup.GridType."],"exampleFix":"// before\ncase PositionSnapGridType.Triangle:\n    ...\ncase PositionSnapGridType.Square:\n    ...\ncase PositionSnapGridType.Circle:\n    ...\ndefault:\n    throw new ArgumentOutOfRangeException(...);\n\n// after — add the missing case\ncase PositionSnapGridType.Hexagon:\n    var hexGrid = new HexagonalPositionSnapGrid();\n    hexGrid.Spacing.BindTo(OsuGridToolboxGroup.GridLineSpacing);\n    positionSnapGrid = hexGrid;\n    break;","handlingStrategy":"type-guard","validationCode":"// Validate the grid type is within the handled set before entering the switch\nvar validTypes = new[] { PositionSnapGridType.Triangle, PositionSnapGridType.Square, PositionSnapGridType.Circle };\nif (!validTypes.Contains(OsuGridToolboxGroup.GridType.Value))\n    throw new ArgumentOutOfRangeException($\"Unhandled grid type: {OsuGridToolboxGroup.GridType.Value}\");","typeGuard":"// Type guard for PositionSnapGridType exhaustiveness\nstatic bool IsSupportedGridType(PositionSnapGridType type)\n    => type is PositionSnapGridType.Triangle\n        or PositionSnapGridType.Square\n        or PositionSnapGridType.Circle;","tryCatchPattern":null,"preventionTips":["When adding a new PositionSnapGridType enum value, use the compiler's exhaustive switch warning (C# 8+ switch expressions) to catch missing cases.","Run a test suite that iterates all enum values through BuildPositionSnapGrid after adding new members."],"tags":["editor","osu-ruleset","enum-exhaustiveness","snap-grid"],"backgroundTag":null,"analyzedSha":"d9c73e12adff2feaae4a3e158d36fe5883faf6ca","analyzedAt":"2026-08-13T14:12:54.015Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}