ppy/osu · error · BeatmapLoadTimeoutException

Timed out while loading beatmap ({beatmapInfo}).

Error message

Timed out while loading beatmap ({beatmapInfo}).

What it means

Thrown by WorkingBeatmap.GetPlayableBeatmap(ruleset, mods) (the 2-arg overload) when the inner call is cancelled by a 10-second CancellationTokenSource. The catch converts OperationCanceledException into BeatmapLoadTimeoutException(BeatmapInfo), signalling the beatmap could not be decoded/converted within the budget. Note: when Debugger.IsAttached the token is CancellationToken.None, so this never fires while debugging.

Source

Thrown at osu.Game/Beatmaps/WorkingBeatmap.cs:273

        }

        #endregion

        #region Playable beatmap

        public IBeatmap GetPlayableBeatmap(IRulesetInfo ruleset, IReadOnlyList<Mod> mods = null)
        {
            try
            {
                using (var cancellationTokenSource = new CancellationTokenSource(10_000))
                {
                    // don't apply the default timeout when debugger is attached (may be breakpointing / debugging).
                    return GetPlayableBeatmap(ruleset, mods ?? Array.Empty<Mod>(), Debugger.IsAttached ? CancellationToken.None : cancellationTokenSource.Token);
                }
            }
            catch (OperationCanceledException)
            {
                throw new BeatmapLoadTimeoutException(BeatmapInfo);
            }
        }

        public virtual IBeatmap GetPlayableBeatmap(IRulesetInfo ruleset, IReadOnlyList<Mod> mods, CancellationToken token)
        {
            var rulesetInstance = ruleset.CreateInstance();

            if (rulesetInstance == null)
                throw new RulesetLoadException("Creating ruleset instance failed when attempting to create playable beatmap.");

            IBeatmapConverter converter = CreateBeatmapConverter(Beatmap, rulesetInstance);

            // Check if the beatmap can be converted
            if (Beatmap.HitObjects.Count > 0 && !converter.CanConvert())
                throw new BeatmapInvalidForRulesetException($"{nameof(Beatmaps.Beatmap)} can not be converted for the ruleset (ruleset: {ruleset.InstantiationInfo}, converter: {converter}).");

            // Apply conversion mods
            foreach (var mod in mods.OfType<IApplicableToBeatmapConverter>())

View on GitHub (pinned to d9c73e12ad)

Solutions

  1. Use the 3-arg overload GetPlayableBeatmap(ruleset, mods, cancellationToken) with your own longer or no cancellation token for batch/offline work.
  2. Investigate the specific beatmap: decode it standalone to find the slow stage (decoder, converter, or a mod) and report/file the offending map.
  3. Ensure disk/realm are healthy and not contended; if running in a tight loop, rate-limit concurrency so a single decode doesn't starve others.

Example fix

// before (10s budget, bypassed under debugger)
IBeatmap playable = working.GetPlayableBeatmap(rulesetInfo, mods);

// after (caller-controlled budget for offline/batch)
using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(1));
IBeatmap playable = working.GetPlayableBeatmap(rulesetInfo, mods, cts.Token);
Defensive patterns

Strategy: try-catch

Validate before calling

// For batch/offline work, prefer the token-controlled overload.
using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(2));
IBeatmap playable = working.GetPlayableBeatmap(rulesetInfo, mods, cts.Token);

Type guard

static bool CanLoadWithinBudget(WorkingBeatmap wb, IRulesetInfo ruleset, IReadOnlyList<Mod> mods, TimeSpan budget)
{
    using var cts = new CancellationTokenSource(budget);
    try { wb.GetPlayableBeatmap(ruleset, mods, cts.Token); return true; }
    catch (OperationCanceledException) { return false; }
}

Try / catch

try { var playable = working.GetPlayableBeatmap(ruleset, mods); }
catch (BeatmapLoadTimeoutException) { /* mark beatmap as problematic, skip or warn user */ }

Prevention

When it happens

Trigger: Calling GetPlayableBeatmap on a very large, corrupt, or pathological beatmap whose decode + ruleset conversion + mod application exceeds 10s. Also triggered by an unresponsive/slow disk under load, or a ruleset/converter that loops heavily on edge-case data.

Common situations: Score simulation/migration over thousands of beatmaps where one stalls; background difficulty calculation; gameplay load on low-end hardware with heavy mod stacks. Disappears under the debugger because the timeout is bypassed — a classic 'works when debugging' symptom.

Understand the failure class

Related errors


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