ppy/osu · error · ArgumentOutOfRangeException

Unsupported grid type.

Error message

Unsupported grid type.

What it means

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.

Source

Thrown at osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs:171

                case PositionSnapGridType.Triangle:
                    var triangularPositionSnapGrid = new TriangularPositionSnapGrid();

                    triangularPositionSnapGrid.Spacing.BindTo(OsuGridToolboxGroup.GridLineSpacing);
                    triangularPositionSnapGrid.GridLineRotation.BindTo(OsuGridToolboxGroup.GridLinesRotation);

                    positionSnapGrid = triangularPositionSnapGrid;
                    break;

                case PositionSnapGridType.Circle:
                    var circularPositionSnapGrid = new CircularPositionSnapGrid();

                    circularPositionSnapGrid.Spacing.BindTo(OsuGridToolboxGroup.GridLineSpacing);

                    positionSnapGrid = circularPositionSnapGrid;
                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(OsuGridToolboxGroup.GridType), OsuGridToolboxGroup.GridType, "Unsupported grid type.");
            }

            // Bind the start position to the toolbox sliders.
            positionSnapGrid.StartPosition.BindTo(OsuGridToolboxGroup.StartPosition);

            positionSnapGrid.RelativeSizeAxes = Axes.Both;
            LayerBelowRuleset.Add(positionSnapGrid);
        }

        protected override ComposeBlueprintContainer CreateBlueprintContainer()
            => new OsuBlueprintContainer(this);

        public override string ConvertSelectionToString()
            => string.Join(',', selectedHitObjects.Cast<OsuHitObject>().OrderBy(h => h.StartTime)
                                                  .Select(h => (h.IndexInCurrentCombo + 1).ToString(CultureInfo.InvariantCulture)));

        // 1,2,3,4 ...
        private static readonly Regex selection_regex = new Regex(@"^\d+(,\d+)*$", RegexOptions.Compiled);

View on GitHub (pinned to d9c73e12ad)

Solutions

  1. Add a case for the new PositionSnapGridType value that instantiates the correct PositionSnapGrid subclass and binds its properties.
  2. If the enum is data-driven, validate the value against the known set before assigning it to OsuGridToolboxGroup.GridType.

Example fix

// before
case PositionSnapGridType.Triangle:
    ...
case PositionSnapGridType.Square:
    ...
case PositionSnapGridType.Circle:
    ...
default:
    throw new ArgumentOutOfRangeException(...);

// after — add the missing case
case PositionSnapGridType.Hexagon:
    var hexGrid = new HexagonalPositionSnapGrid();
    hexGrid.Spacing.BindTo(OsuGridToolboxGroup.GridLineSpacing);
    positionSnapGrid = hexGrid;
    break;
Defensive patterns

Strategy: type-guard

Validate before calling

// Validate the grid type is within the handled set before entering the switch
var validTypes = new[] { PositionSnapGridType.Triangle, PositionSnapGridType.Square, PositionSnapGridType.Circle };
if (!validTypes.Contains(OsuGridToolboxGroup.GridType.Value))
    throw new ArgumentOutOfRangeException($"Unhandled grid type: {OsuGridToolboxGroup.GridType.Value}");

Type guard

// Type guard for PositionSnapGridType exhaustiveness
static bool IsSupportedGridType(PositionSnapGridType type)
    => type is PositionSnapGridType.Triangle
        or PositionSnapGridType.Square
        or PositionSnapGridType.Circle;

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of ppy/osu@d9c73e12ad (2026-08-13). Data as JSON: /api/errors/16fbd3f4d0e876d6. Report an issue: GitHub.