ppy/osu · error · InvalidOperationException

Ruleset with ID of {RulesetID} not found locally

Error message

Ruleset with ID of {RulesetID} not found locally

What it means

Thrown by SoloScoreInfo.ToScoreInfo when converting an API score into a local ScoreInfo. The method asks the RulesetStore for the score's RulesetID and throws InvalidOperationException if the store has no matching ruleset. The store only contains ruleset assemblies that are installed and enabled on this client.

Source

Thrown at osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs:186

        #endregion

        /// <summary>
        /// Whether this <see cref="ScoreInfo"/> represents a legacy (osu!stable) score.
        /// </summary>
        [JsonIgnore]
        public bool IsLegacyScore => LegacyScoreId != null;

        public override string ToString() => $"score_id: {ID} user_id: {UserID}";

        /// <summary>
        /// Create a <see cref="ScoreInfo"/> from an API score instance.
        /// </summary>
        /// <param name="rulesets">A ruleset store, used to populate a ruleset instance in the returned score.</param>
        /// <param name="beatmap">An optional beatmap, copied into the returned score (for cases where the API does not populate the beatmap).</param>
        /// <returns></returns>
        public ScoreInfo ToScoreInfo(RulesetStore rulesets, BeatmapInfo? beatmap = null)
        {
            var ruleset = rulesets.GetRuleset(RulesetID) ?? throw new InvalidOperationException($"Ruleset with ID of {RulesetID} not found locally");

            var rulesetInstance = ruleset.CreateInstance();

            var mods = Mods.Select(apiMod => apiMod.ToMod(rulesetInstance)).ToArray();

            var scoreInfo = ToScoreInfo(mods, beatmap);
            scoreInfo.Ruleset = ruleset;

            return scoreInfo;
        }

        /// <summary>
        /// Create a <see cref="ScoreInfo"/> from an API score instance.
        /// </summary>
        /// <param name="mods">The mod instances, resolved from a ruleset.</param>
        /// <param name="beatmap">The object to populate the scores' beatmap with.
        ///<list type="bullet">
        /// <item>If this is a <see cref="BeatmapInfo"/> type, then the score will be fully populated with the given object.</item>

View on GitHub (pinned to d9c73e12ad)

Solutions

  1. Verify all required ruleset assemblies are present and enabled on the client (check RulesetStore.AvailableRulesets).
  2. Guard before calling: if (!rulesets.AvailableRulesets.Any(r => r.OnlineID == score.RulesetID)) skip or filter the score.
  3. Wrap the call site in try/catch(InvalidOperationException) and drop the unresolvable score from the list rather than crashing the import/display flow.

Example fix

// before
var info = score.ToScoreInfo(rulesets, beatmap);

// after
var ruleset = rulesets.GetRuleset(score.RulesetID);
if (ruleset == null) continue; // unknown ruleset for this client
var info = score.ToScoreInfo(rulesets, beatmap);
Defensive patterns

Strategy: validation

Validate before calling

var ruleset = rulesets.GetRuleset(score.RulesetID);
if (ruleset == null)
{
    // unknown ruleset for this client; skip this score
    continue;
}

Type guard

// nullable ruleset check before conversion
RulesetInfo? ResolveRuleset(RulesetStore store, SoloScoreInfo score)
    => store.GetRuleset(score.RulesetID);

Try / catch

try { var info = score.ToScoreInfo(rulesets, beatmap); }
catch (InvalidOperationException) { /* filter score: ruleset unavailable locally */ }

Prevention

When it happens

Trigger: Calling ToScoreInfo(rulesets, beatmap) on a SoloScoreInfo whose RulesetID is not returned by rulesets.GetRuleset(RulesetID). Happens for scores originating from a ruleset the client does not have loaded (e.g. a custom ruleset DLL, or a newer ruleset than the client version).

Common situations: Client is missing the ruleset DLL the server used (version skew after an osu! update, disabled/removed ruleset, or a modded ruleset). Attempting to display/import a score from a ruleset the user uninstalled.

Related errors


AI-assisted analysis of ppy/osu@d9c73e12ad (2026-08-13). Data as JSON: /api/errors/612598a91e09eb12. Report an issue: GitHub.