ppy/osu · error · InvalidOperationException
Unknown hit object type.
Error message
Unknown hit object type.
What it means
TaikoAutoGenerator generates replay frames by switching on the type of each hit object (Hit, DrumRoll, and Swell are handled). The default case throws InvalidOperationException for any unhandled type, indicating a new or unexpected hit object subclass was encountered during auto-replay generation.
Source
Thrown at osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs:115
if (hit.Type == HitType.Centre)
{
actions = hit.IsStrong
? new[] { TaikoAction.LeftCentre, TaikoAction.RightCentre }
: new[] { hitButton ? TaikoAction.LeftCentre : TaikoAction.RightCentre };
}
else
{
actions = hit.IsStrong
? new[] { TaikoAction.LeftRim, TaikoAction.RightRim }
: new[] { hitButton ? TaikoAction.LeftRim : TaikoAction.RightRim };
}
Frames.Add(new TaikoReplayFrame(h.StartTime, actions));
break;
}
default:
throw new InvalidOperationException("Unknown hit object type.");
}
var nextHitObject = GetNextObject(i); // Get the next object that requires pressing the same button
bool canDelayKeyUp = nextHitObject == null || nextHitObject.StartTime > endTime + KEY_UP_DELAY;
double calculatedDelay = canDelayKeyUp ? KEY_UP_DELAY : (nextHitObject.AsNonNull().StartTime - endTime) * 0.9;
Frames.Add(new TaikoReplayFrame(endTime + calculatedDelay));
hitButton = !hitButton;
}
}
}
}
View on GitHub (pinned to d9c73e12ad)
Solutions
- Add a case for the new hit object type in the switch that generates appropriate replay frames.
- If the unhandled type is unexpected, audit the beatmap parsing to determine why an unknown type was created.
Example fix
// before
case Hit h:
...
case DrumRoll d:
...
case Swell s:
...
default:
throw new InvalidOperationException("Unknown hit object type.");
// after — add the missing case
case DrumRoll d:
...
case Swell s:
...
case SwapHit sw:
// generate replay frames for the new type
Frames.Add(new TaikoReplayFrame(sw.StartTime, TaikoAction.LeftCentre, TaikoAction.RightCentre));
break; Defensive patterns
Strategy: type-guard
Validate before calling
// Check the hit object type before adding to the beatmap or generating replays
static bool IsSupportedTaikoHitObject(HitObject ho)
=> ho is Hit or DrumRoll or Swell; Type guard
// Type guard for Taiko hit object types
static bool IsSupportedTaikoHitObject(HitObject ho)
=> ho is Hit or DrumRoll or Swell; Prevention
- When adding a new Taiko hit object type, update the auto-replay generator's switch in the same commit.
- Add a test that iterates all hit object types through the auto generator.
- Use pattern matching with exhaustive compiler warnings if possible.
When it happens
Trigger: A Taiko hit object of a type not covered by the switch (not Hit, not DrumRoll (IHasDuration), not Swell) is present in the beatmap when the auto generator processes it.
Common situations: Extending the Taiko ruleset with a new hit object type without updating the auto-replay generator; ruleset forking; deserialization of a beatmap with custom hit object types that the generator doesn't recognize.
Related errors
- Invalid component type: {component}
- Invalid result type: {result}
- Unsupported grid type.
- Unsupported animation style
- Use override with HitType parameter instead
AI-assisted analysis of ppy/osu@d9c73e12ad (2026-08-13).
Data as JSON: /api/errors/e6726b557820e623.
Report an issue: GitHub.