{"record":{"id":"e6726b557820e623","repo":"ppy/osu","slug":"unknown-hit-object-type","errorCode":null,"errorMessage":"Unknown hit object type.","messagePattern":"Unknown hit object type\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs","lineNumber":115,"sourceCode":"                        if (hit.Type == HitType.Centre)\r\n                        {\r\n                            actions = hit.IsStrong\r\n                                ? new[] { TaikoAction.LeftCentre, TaikoAction.RightCentre }\r\n                                : new[] { hitButton ? TaikoAction.LeftCentre : TaikoAction.RightCentre };\r\n                        }\r\n                        else\r\n                        {\r\n                            actions = hit.IsStrong\r\n                                ? new[] { TaikoAction.LeftRim, TaikoAction.RightRim }\r\n                                : new[] { hitButton ? TaikoAction.LeftRim : TaikoAction.RightRim };\r\n                        }\r\n\r\n                        Frames.Add(new TaikoReplayFrame(h.StartTime, actions));\r\n                        break;\r\n                    }\r\n\r\n                    default:\r\n                        throw new InvalidOperationException(\"Unknown hit object type.\");\r\n                }\r\n\r\n                var nextHitObject = GetNextObject(i); // Get the next object that requires pressing the same button\r\n\r\n                bool canDelayKeyUp = nextHitObject == null || nextHitObject.StartTime > endTime + KEY_UP_DELAY;\r\n                double calculatedDelay = canDelayKeyUp ? KEY_UP_DELAY : (nextHitObject.AsNonNull().StartTime - endTime) * 0.9;\r\n                Frames.Add(new TaikoReplayFrame(endTime + calculatedDelay));\r\n\r\n                hitButton = !hitButton;\r\n            }\r\n        }\r\n    }\r\n}\r\n","sourceCodeStart":97,"sourceCodeEnd":129,"githubUrl":"https://github.com/ppy/osu/blob/d9c73e12adff2feaae4a3e158d36fe5883faf6ca/osu.Game.Rulesets.Taiko/Replays/TaikoAutoGenerator.cs#L97-L129","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ncase Hit h:\n    ...\ncase DrumRoll d:\n    ...\ncase Swell s:\n    ...\ndefault:\n    throw new InvalidOperationException(\"Unknown hit object type.\");\n\n// after — add the missing case\ncase DrumRoll d:\n    ...\ncase Swell s:\n    ...\ncase SwapHit sw:\n    // generate replay frames for the new type\n    Frames.Add(new TaikoReplayFrame(sw.StartTime, TaikoAction.LeftCentre, TaikoAction.RightCentre));\n    break;","handlingStrategy":"type-guard","validationCode":"// Check the hit object type before adding to the beatmap or generating replays\nstatic bool IsSupportedTaikoHitObject(HitObject ho)\n    => ho is Hit or DrumRoll or Swell;","typeGuard":"// Type guard for Taiko hit object types\nstatic bool IsSupportedTaikoHitObject(HitObject ho)\n    => ho is Hit or DrumRoll or Swell;","tryCatchPattern":null,"preventionTips":["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."],"tags":["taiko-ruleset","replay","enum-exhaustiveness","auto-generator"],"backgroundTag":null,"analyzedSha":"d9c73e12adff2feaae4a3e158d36fe5883faf6ca","analyzedAt":"2026-08-13T14:12:54.015Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}