{"record":{"id":"fe21b798dee4f382","repo":"ppy/osu","slug":"ruleset-could-not-be-loaded-instantiation-failure","errorCode":null,"errorMessage":"Ruleset could not be loaded (Instantiation failure)","messagePattern":"Ruleset could not be loaded \\(Instantiation failure\\)","errorType":"exception","errorClass":"RulesetLoadException","httpStatus":null,"severity":"error","filePath":"osu.Game/Rulesets/RulesetInfo.cs","lineNumber":110,"sourceCode":"            InstantiationInfo = InstantiationInfo,\r\n            Available = Available,\r\n            LastAppliedDifficultyVersion = LastAppliedDifficultyVersion,\r\n        };\r\n\r\n        public Ruleset CreateInstance()\r\n        {\r\n            if (!Available)\r\n                throw new RulesetLoadException(@\"Ruleset not available\");\r\n\r\n            var type = Type.GetType(InstantiationInfo);\r\n\r\n            if (type == null)\r\n                throw new RulesetLoadException(@\"Type lookup failure\");\r\n\r\n            var ruleset = Activator.CreateInstance(type) as Ruleset;\r\n\r\n            if (ruleset == null)\r\n                throw new RulesetLoadException(@\"Instantiation failure\");\r\n\r\n            // overwrite the pre-populated RulesetInfo with a potentially database attached copy.\r\n            // TODO: figure if we still want/need this after switching to realm.\r\n            // ruleset.RulesetInfo = this;\r\n\r\n            return ruleset;\r\n        }\r\n    }\r\n}\r\n","sourceCodeStart":92,"sourceCodeEnd":120,"githubUrl":"https://github.com/ppy/osu/blob/d9c73e12adff2feaae4a3e158d36fe5883faf6ca/osu.Game/Rulesets/RulesetInfo.cs#L92-L120","documentation":"Thrown by RulesetInfo.CreateInstance when Activator.CreateInstance(type) succeeds but the resulting object cannot be cast to Ruleset. This means the type referenced by InstantiationInfo exists in the loaded assemblies but does not inherit from osu.Game.Rulesets.Ruleset. It is distinct from the 'Type lookup failure' sibling (type == null) and 'Ruleset not available' (Available flag off).","triggerScenarios":"InstantiationInfo points to a Type that is not a Ruleset subclass (e.g. a class named similarly, a RulesetInfo subclass, or a stub). Occurs when a ruleset assembly is present but the declared InstantiationInfo string names a non-Ruleset type.","commonSituations":"Migrating a custom ruleset that renamed its primary Ruleset class but left the database/InstantiationInfo pointing at the old name; corrupted RulesetInfo rows after an incompatible ruleset update; a ruleset DLL that only partially matches the expected API.","solutions":["Inspect the value of InstantiationInfo for the offending ruleset and confirm the named type is a non-abstract Ruleset subclass in a loaded assembly.","If the ruleset type was renamed/moved, update InstantiationInfo (or delete and re-register the RulesetInfo row) to point at the correct fully-qualified type name.","If the ruleset assembly is missing or incompatible, remove/disable the ruleset entry rather than letting instantiation proceed.","Wrap CreateInstance() calls in ruleset-loading UI with a RulesetLoadException handler to surface a user-facing message instead of crashing."],"exampleFix":"// before\nvar type = Type.GetType(InstantiationInfo);\nvar ruleset = Activator.CreateInstance(type) as Ruleset;\n\n// after (diagnostic)\nvar type = Type.GetInstance(InstantiationInfo);\nif (type != null && !typeof(Ruleset).IsAssignableFrom(type))\n    throw new RulesetLoadException($@\"Type {type.FullName} is not a Ruleset subclass.\");\nvar ruleset = Activator.CreateInstance(type) as Ruleset;","handlingStrategy":"validation","validationCode":"var type = Type.GetType(instantiationInfo);\nif (type == null || !typeof(Ruleset).IsAssignableFrom(type) || type.IsAbstract)\n    return; // skip; do not call CreateInstance()\nvar ruleset = (Ruleset)Activator.CreateInstance(type);","typeGuard":"static bool IsInstantiableRuleset(string instantiationInfo)\n    => Type.GetType(instantiationInfo) is Type t\n       && typeof(Ruleset).IsAssignableFrom(t)\n       && !t.IsAbstract;","tryCatchPattern":"try { return rulesetInfo.CreateInstance(); }\ncatch (RulesetLoadException ex) { Logger.Log($\"Ruleset load failed: {ex.Message}\"); return null; }","preventionTips":["Keep InstantiationInfo in sync with the actual Ruleset type name after renames.","Validate InstantiationInfo against loaded assemblies before invoking CreateInstance.","Treat a failed ruleset load as a disabled ruleset, not a crash."],"tags":["ruleset","reflection","instantiation","activator"],"backgroundTag":null,"analyzedSha":"d9c73e12adff2feaae4a3e158d36fe5883faf6ca","analyzedAt":"2026-08-13T14:12:54.015Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}