fullstackhero/dotnet-starter-kit · error · InvalidOperationException
File type ' ' is not allowed. Allowed
Error message
File type '{extension}' is not allowed. Allowed: {string.Join(", ", rules.AllowedExtensions)} What it means
LocalStorageService.UploadAsync resolves the FileTypeRules for the requested FileType and validates the uploaded file's extension against rules.AllowedExtensions (case-insensitive). If the extension is missing or not whitelisted, it throws InvalidOperationException before any bytes are written. This is a deliberate security guard against uploading disallowed file types.
Solutions
- Upload a file whose extension is in the AllowedExtensions list for the chosen FileType.
- Extend rules.AllowedExtensions in FileTypeMetadata if the type is legitimately allowed.
- Ensure the client sends the real file name with its extension, not a blob name or GUID without extension.
- Validate the extension in the UI before calling the API.
Example fix
// before
await storage.UploadAsync(new UploadRequest { FileName = "photo", FileType = FileType.Image, Data = bytes });
// after
var ext = Path.GetExtension("photo.jpg"); // send real name with extension
if (!FileTypeMetadata.GetRules(FileType.Image).AllowedExtensions.Contains(ext))
throw new ArgumentException($"Unsupported image extension: {ext}");
await storage.UploadAsync(new UploadRequest { FileName = "photo.jpg", FileType = FileType.Image, Data = bytes }); Defensive patterns
Strategy: validation
Validate before calling
var ext = Path.GetExtension(fileName);
var rules = FileTypeMetadata.GetRules(fileType);
if (string.IsNullOrWhiteSpace(ext) || !rules.AllowedExtensions.Contains(ext, StringComparer.OrdinalIgnoreCase))
throw new ArgumentException($"Extension '{ext}' not allowed for {fileType}."); Type guard
bool IsAllowedExtension(string? ext, FileTypeRules rules) =>
!string.IsNullOrWhiteSpace(ext) && rules.AllowedExtensions.Contains(ext, StringComparer.OrdinalIgnoreCase); Try / catch
try {
await storage.UploadAsync(request);
} catch (InvalidOperationException ex) when (ex.Message.StartsWith("File type")) {
return Results.BadRequest(new { error = "Unsupported file type", detail = ex.Message });
} Prevention
- Mirror AllowedExtensions in the frontend file-picker accept attribute.
- Never strip or rewrite the file name before upload.
- Add new supported formats to FileTypeMetadata first, then enable them in the UI.
When it happens
Trigger: UploadAsync called with a FileName that has no extension, an empty/whitespace extension, or an extension not in the AllowedExtensions list for that FileType (e.g. uploading a .exe as an Image).
Common situations: Users uploading files with no extension (macOS/Linux exports, dotfiles); clients renaming files; mismatch between the file type selected in the UI and the actual file; adding a new extension to the UI but not to FileTypeMetadata rules.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- File type ' ' is not allowed. Allowed
- Storage quota exceeded
- File exceeds max size of
- File exceeds max size of
- Extension ' ' not allowed for category ' '.
AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15).
Data as JSON: /api/errors/a143393ec88d7389.
Report an issue: GitHub.
Appendix: source
Thrown at src/BuildingBlocks/Storage/Local/LocalStorageService.cs:44
ArgumentNullException.ThrowIfNull(environment);
_rootPath = string.IsNullOrWhiteSpace(environment.WebRootPath)
? Path.Combine(environment.ContentRootPath, "wwwroot")
: environment.WebRootPath;
_contentTypeProvider = new FileExtensionContentTypeProvider();
}
public async Task<string> UploadAsync<T>(FileUploadRequest request, FileType fileType, CancellationToken cancellationToken = default)
where T : class
{
ArgumentNullException.ThrowIfNull(request);
var rules = FileTypeMetadata.GetRules(fileType);
var extension = Path.GetExtension(request.FileName);
if (string.IsNullOrWhiteSpace(extension) ||
!rules.AllowedExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
{
throw new InvalidOperationException($"File type '{extension}' is not allowed. Allowed: {string.Join(", ", rules.AllowedExtensions)}");
}
if (request.Data.Count > rules.MaxSizeInMB * 1024 * 1024)
{
throw new InvalidOperationException($"File exceeds max size of {rules.MaxSizeInMB} MB.");
}
#pragma warning disable CA1308 // folder names are intentionally lower-case for URLs/paths
var folder = FolderSanitizer().Replace(typeof(T).Name.ToLowerInvariant(), "_");
#pragma warning restore CA1308
var safeFileName = $"{Guid.NewGuid():N}_{SanitizeFileName(request.FileName)}";
var relativePath = Path.Combine(UploadBasePath, folder, safeFileName);
var fullPath = Path.Combine(_rootPath, relativePath);
Directory.CreateDirectory(Path.GetDirectoryName(fullPath)!);
await File.WriteAllBytesAsync(fullPath, request.Data.ToArray(), cancellationToken);
View on GitHub (pinned to 3f2959e683)