{"record":{"id":"a1c321315aa7c8b9","repo":"ppy/osu","slug":"mascot-animations-for-state-state-are-not-suppor","errorCode":null,"errorMessage":"Mascot animations for state {state} are not supported","messagePattern":"Mascot animations for state (.+?) are not supported","errorType":"exception","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"warning","filePath":"osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs","lineNumber":73,"sourceCode":"\r\n            textureAnimation.GotoFrame(currentFrame);\r\n            currentFrame = (currentFrame + 1) % textureAnimation.FrameCount;\r\n        }\r\n\r\n        private static TextureAnimation createTextureAnimation(TaikoMascotAnimationState state)\r\n        {\r\n            switch (state)\r\n            {\r\n                case TaikoMascotAnimationState.Clear:\r\n                    return new ClearMascotTextureAnimation();\r\n\r\n                case TaikoMascotAnimationState.Idle:\r\n                case TaikoMascotAnimationState.Kiai:\r\n                case TaikoMascotAnimationState.Fail:\r\n                    return new ManualMascotTextureAnimation(state);\r\n\r\n                default:\r\n                    throw new ArgumentOutOfRangeException(nameof(state), $\"Mascot animations for state {state} are not supported\");\r\n            }\r\n        }\r\n\r\n        private partial class ManualMascotTextureAnimation : TextureAnimation\r\n        {\r\n            private readonly TaikoMascotAnimationState state;\r\n\r\n            public ManualMascotTextureAnimation(TaikoMascotAnimationState state)\r\n            {\r\n                this.state = state;\r\n\r\n                IsPlaying = false;\r\n            }\r\n\r\n            [BackgroundDependencyLoader]\r\n            private void load(ISkinSource source)\r\n            {\r\n                ISkin? skin = source.FindProvider(s => getAnimationFrame(s, state, 0) != null);\r","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/ppy/osu/blob/d9c73e12adff2feaae4a3e158d36fe5883faf6ca/osu.Game.Rulesets.Taiko/UI/TaikoMascotAnimation.cs#L55-L91","documentation":"Thrown by createTextureAnimation when the TaikoMascotAnimationState enum value passed to the constructor is not one of the handled cases (Clear, Idle, Kiai, Fail). The switch covers all four declared enum members, so the default branch only fires when an invalid/cast enum value (e.g. (TaikoMascotAnimationState)99) is supplied. This is a defensive guard against corruption or misuse rather than a normal runtime path.","triggerScenarios":"Constructing `new TaikoMascotAnimation(state)` where `state` is an enum value outside the four valid members — typically produced by casting an arbitrary integer to TaikoMascotAnimationState, or by a deserialized/reflected value that wasn't validated.","commonSituations":"Deserialization of a corrupted mascot state from a save file or network payload; a ruleset mod that extends the enum or passes an integer state index incorrectly; test code that casts a raw int without bounds-checking.","solutions":["Ensure only the four valid TaikoMascotAnimationState values (Idle, Clear, Kiai, Fail) are ever passed to the TaikoMascotAnimation constructor.","If the state originates from an external source (deserialization, config), validate it with Enum.IsDefined before constructing.","If extending the mascot system with new states, add a matching case to the switch in createTextureAnimation at TaikoMascotAnimation.cs:62."],"exampleFix":"// before\nvar state = (TaikoMascotAnimationState)rawIndex;\nvar mascot = new TaikoMascotAnimation(state);\n\n// after\nif (!Enum.IsDefined(typeof(TaikoMascotAnimationState), rawIndex))\n    throw new ArgumentOutOfRangeException(nameof(rawIndex));\nvar state = (TaikoMascotAnimationState)rawIndex;\nvar mascot = new TaikoMascotAnimation(state);","handlingStrategy":"type-guard","validationCode":"// Validate before constructing\nif (!Enum.IsDefined(typeof(TaikoMascotAnimationState), state))\n    throw new ArgumentOutOfRangeException(nameof(state), $\"Invalid mascot state: {state}\");\nvar animation = new TaikoMascotAnimation(state);","typeGuard":"static bool IsValidMascotState(TaikoMascotAnimationState state)\n    => Enum.IsDefined(typeof(TaikoMascotAnimationState), state);","tryCatchPattern":null,"preventionTips":["Never cast raw integers to TaikoMascotAnimationState without Enum.IsDefined validation.","If deserializing mascot state from external data, validate before use.","If extending the enum, update the switch in createTextureAnimation immediately."],"tags":["osu-taiko","enum-validation","animation","defensive-guard"],"backgroundTag":null,"analyzedSha":"d9c73e12adff2feaae4a3e158d36fe5883faf6ca","analyzedAt":"2026-08-13T14:12:54.015Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}