ppy/osu · error · InvalidOperationException
Beatmap file {b.File!.Filename} could not be opened!
Error message
Beatmap file {b.File!.Filename} could not be opened! What it means
Thrown by LegacyBeatmapExporter.ExportAsync when GetFileContents(b.BeatmapSet, b.File) returns null while exporting a single beatmap to .osz. GetFileContents resolves the file's on-disk storage path via UserFileStorage.GetStream; a null result means the backing file blob is missing from the realm file store even though the BeatmapInfo references it. The surrounding try/catch cancels the progress notification, deletes the partially-created export file, and rethrows.
Source
Thrown at osu.Game/Database/LegacyBeatmapExporter.cs:242
string filename = NamingUtils.GetNextBestFilename(existingExports, $"{itemFilename}{osu_extension}");
ProgressNotification notification = new ProgressNotification
{
State = ProgressNotificationState.Active,
Text = NotificationsStrings.FileExportOngoing(itemFilename),
};
PostNotification?.Invoke(notification);
try
{
beatmap.PerformRead(b =>
{
using var exportStream = ExportStorage.CreateFileSafely(filename);
using var inputFile = GetFileContents(b.BeatmapSet!, b.File!);
if (inputFile == null)
throw new InvalidOperationException($"Beatmap file {b.File!.Filename} could not be opened!");
inputFile.CopyTo(exportStream);
});
}
catch
{
notification.State = ProgressNotificationState.Cancelled;
// cleanup if export is failed or canceled.
ExportStorage.Delete(filename);
throw;
}
notification.CompletionText = NotificationsStrings.FileExportFinished(itemFilename);
notification.CompletionClickAction = () => ExportStorage.PresentFileExternally(filename);
notification.State = ProgressNotificationState.Completed;
});
}
View on GitHub (pinned to d9c73e12ad)
Solutions
- Verify the beatmap's file actually exists on disk before exporting: check b.BeatmapSet.Files for the named file and RealmFileStore.Store.GetStream(file.File.GetStoragePath()) returns non-null.
- If the file is genuinely missing, repair or re-import the beatmap set (re-download or re-import the .osz) so the backing blob is present, then retry the export.
- If recurring across many beatmaps, run a storage integrity check / re-link missing files; investigate whether a prior MigratableStorage.Migrate or file cleanup deleted blobs without updating realm.
Example fix
// before
beatmap.PerformRead(b =>
{
using var inputFile = GetFileContents(b.BeatmapSet!, b.File!);
if (inputFile == null)
throw new InvalidOperationException($"Beatmap file {b.File!.Filename} could not be opened!");
// ...
});
// after (guard at call site, degrade gracefully)
if (beatmap.PerformRead(b => RealmFileStore.Store.GetStream(b.File!.File.GetStoragePath())) == null)
{
notification.State = ProgressNotificationState.Cancelled;
return;
} Defensive patterns
Strategy: validation
Validate before calling
// Verify the beatmap's file blob exists on disk before exporting.
bool canExport = beatmap.PerformRead(b =>
{
if (b.File == null || b.BeatmapSet == null) return false;
string path = b.File.File.GetStoragePath();
return !string.IsNullOrEmpty(path) && realmFileStore.Store.GetStream(path) != null;
});
if (!canExport) { /* show 'file missing' notification */ } Type guard
static bool HasBackingFile(BeatmapSetInfo set, INamedFileUsage file, RealmFileStore store)
=> file?.File != null && store.Store.GetStream(file.File.GetStoragePath()) != null; Try / catch
try { await exporter.ExportAsync(beatmap); }
catch (InvalidOperationException ex) when (ex.Message.Contains("could not be opened"))
{
Notifications.Post(new SimpleNotification { Text = "The beatmap file is missing from disk. Try re-importing it." });
} Prevention
- Never delete or move files under the realm file store except through ModelManager/realmFileStore APIs.
- After a storage migration, run an integrity pass that verifies every RealmNamedFileUsage resolves to a non-null stream.
- When re-importing or replacing beatmap sets, ensure the old File references are updated atomically.
When it happens
Trigger: Calling ExportAsync(beatmap) on a Live<BeatmapInfo> whose b.File / b.BeatmapSet points at a RealmNamedFileUsage whose underlying RealmFile no longer exists on disk (store path missing, file deleted out-of-band, or corrupted realm). The null check at line 241 fires before CopyTo would NRE.
Common situations: User opens a beatmap info context menu and picks 'Export'; the beatmap set had files pruned or migrated incompletely (e.g. after a failed storage migration, manual deletion of files/ directory, or a realm restore from a backup whose blobs weren't copied). Also seen when a beatmap's File navigation property is stale after the file was replaced/deleted in another transaction.
Related errors
- Filename ""{filename}"" is not allowed.
- Beatmap contains no hit objects!
- Cannot recalculate score multiplier as TotalScoreWithoutMods
- Failed to import new beatmap
- Error when exporting {model.GetDisplayString()}: Multiple fi
AI-assisted analysis of ppy/osu@d9c73e12ad (2026-08-13).
Data as JSON: /api/errors/c70dcb5eb6abf890.
Report an issue: GitHub.