ppy/osu · error · InvalidOperationException
Filename "" "" is not allowed.
Error message
Filename ""{filename}"" is not allowed. What it means
Thrown by ModelManager<TModel>.AddFile after ToStandardisedPath() if FilesystemSanityCheckHelpers.IncursPathTraversalRisk(filename) is true. It is a hard security guard rejecting filenames that could escape the model's file directory via '..' segments, absolute paths, or other traversal patterns. Runs inside an ongoing realm transaction.
Solutions
- Sanitise the filename before calling AddFile: strip directory components with Path.GetFileName(filename) and reject/replace any path separators or '..'.
- Validate with the same helper the manager uses: guard with if (FilesystemSanityCheckHelpers.IncursPathTraversalRisk(filename)) return early or normalise.
- Ensure user-facing filename fields are passed through ToStandardisedPath() and a GetValidFilename()-style normaliser upstream so only a relative leaf name reaches AddFile.
Example fix
// before
modelManager.AddFile(item, stream, @"../../etc/evil.osu", realm);
// after
string safeName = Path.GetFileName(filename).GetValidFilename();
if (FilesystemSanityCheckHelpers.IncursPathTraversalRisk(safeName))
throw new ArgumentException($"Refusing unsafe filename: {filename}");
modelManager.AddFile(item, stream, safeName, realm); Defensive patterns
Strategy: validation
Validate before calling
string safe = Path.GetFileName(filename).ToStandardisedPath();
if (FilesystemSanityCheckHelpers.IncursPathTraversalRisk(safe))
throw new ArgumentException($"Unsafe filename: {filename}");
modelManager.AddFile(item, stream, safe, realm); Type guard
static bool IsSafeFilename(string filename)
=> !string.IsNullOrWhiteSpace(filename)
&& !Path.IsPathRooted(filename)
&& !filename.Contains("..")
&& !FilesystemSanityCheckHelpers.IncursPathTraversalRisk(filename); Try / catch
try { modelManager.AddFile(item, stream, filename, realm); }
catch (InvalidOperationException ex) when (ex.Message.Contains("is not allowed"))
{ /* log offending filename, reject user input */ } Prevention
- Always reduce user-supplied paths to a leaf name with Path.GetFileName before storing.
- Run filenames through GetValidFilename() + ToStandardisedPath() at the input boundary.
- Treat any separator ('\\', '/') in a stored filename as a red flag and reject.
When it happens
Trigger: Calling modelManager.AddFile(item, stream, filename, realm) with a filename containing '../', leading drive/root separators, backslash-based traversal, or any pattern FilesystemSanityCheckHelpers flags. Happens during editor save, import merge, or programmatic file addition.
Common situations: Filenames sourced from untrusted input (downloaded archives, external editor imports, user-typed paths). A ruleset/beatmap editor that constructs filenames by joining user strings without sanitising. Cross-platform path normalisation surprises (backslashes on Windows interpreted as traversal).
Related errors
- Beatmap file could not be opened!
- Destination provided already has files or directories…
- Destination provided is already the current location
- Destination provided is inside the source
- Filename " " is not allowed.
AI-assisted analysis of ppy/osu@d9c73e12ad (2026-08-13).
Data as JSON: /api/errors/e83e4e89ea08be2d.
Report an issue: GitHub.
Appendix: source
Thrown at osu.Game/Database/ModelManager.cs:93
}
/// <summary>
/// Replace a file from within an ongoing realm transaction.
/// </summary>
public void ReplaceFile(RealmNamedFileUsage file, Stream contents, Realm realm)
{
file.File = realmFileStore.Add(contents, realm);
}
/// <summary>
/// Add a file from within an ongoing realm transaction. If the file already exists, it is overwritten.
/// </summary>
public void AddFile(TModel item, Stream contents, string filename, Realm realm)
{
filename = filename.ToStandardisedPath();
if (FilesystemSanityCheckHelpers.IncursPathTraversalRisk(filename))
throw new InvalidOperationException($@"Filename ""{filename}"" is not allowed.");
var existing = item.GetFile(filename);
if (existing != null)
{
ReplaceFile(existing, contents, realm);
return;
}
var file = realmFileStore.Add(contents, realm);
var namedUsage = new RealmNamedFileUsage(file, filename);
item.Files.Add(namedUsage);
}
/// <summary>
/// Delete multiple items.
/// This will post notifications tracking progress.
View on GitHub (pinned to d9c73e12ad)