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
- 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.
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 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.
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
- Cannot Begin a rotate operation while another is in progress
- Cannot Update a rotate operation without calling Begin first
- Cannot Commit a rotate operation without calling Begin first
- Cannot Begin a scale operation while another is in progress!
- Cannot Update a scale operation without calling Begin first!
AI-assisted analysis of ppy/osu@d9c73e12ad (2026-08-13).
Data as JSON: /api/errors/16fbd3f4d0e876d6.
Report an issue: GitHub.