fullstackhero/dotnet-starter-kit · error · InvalidOperationException

File exceeds max size of

Error message

File exceeds max size of {rules.MaxSizeInMB} MB.

What it means

S3StorageService.UploadAsync enforces the per-FileType maximum size (rules.MaxSizeInMB) by comparing request.Data.Count to the cap in bytes, throwing InvalidOperationException before the S3 PutObject. This prevents oversized multipart bodies and S3 storage cost blowups.

Solutions

  1. Compress or split the payload before upload.
  2. Increase rules.MaxSizeInMB for the FileType if the policy allows it.
  3. Use S3 multipart upload / presigned direct upload for very large files.
  4. Enforce the same size limit in the frontend before calling the API.

Example fix

// before
await s3.UploadAsync(new UploadRequest { FileName = name, FileType = FileType.Image, Data = allBytes });

// after
var rules = FileTypeMetadata.GetRules(FileType.Image);
var maxBytes = (long)rules.MaxSizeInMB * 1024 * 1024;
if (allBytes.Length > maxBytes) return Results.Problem("Image too large", statusCode: 413);
await s3.UploadAsync(new UploadRequest { FileName = name, FileType = FileType.Image, Data = allBytes });
Defensive patterns

Strategy: validation

Validate before calling

var rules = FileTypeMetadata.GetRules(fileType);
var maxBytes = (long)rules.MaxSizeInMB * 1024 * 1024;
if (data.Length > maxBytes)
    throw new ArgumentException($"File exceeds max size of {rules.MaxSizeInMB} MB.");

Type guard

bool IsWithinSizeLimit(long byteCount, FileTypeRules rules) => byteCount <= (long)rules.MaxSizeInMB * 1024 * 1024;

Try / catch

try {
    await s3Storage.UploadAsync(request);
} catch (InvalidOperationException ex) when (ex.Message.Contains("exceeds max size")) {
    return Results.Problem(ex.Message, statusCode: 413);
}

Prevention

When it happens

Trigger: UploadAsync with request.Data byte count greater than rules.MaxSizeInMB * 1024 * 1024 for the FileType.

Common situations: Large media uploads; S3 provider switched in while limits are lower than local; ETL/bulk import pushing whole datasets as one file; client-side pre-upload size checks not in place.

Understand the failure class

Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15). Data as JSON: /api/errors/fb0120f088ff8694. Report an issue: GitHub.

Appendix: source

Thrown at src/BuildingBlocks/Storage/S3/S3StorageService.cs:56

            throw new InvalidOperationException("Storage:S3:Bucket is required when using S3 storage.");
        }
    }

    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.");
        }

        var key = BuildKey<T>(SanitizeFileName(request.FileName));

        using var stream = new MemoryStream([.. request.Data]);

        var putRequest = new PutObjectRequest
        {
            BucketName = _options.Bucket,
            Key = key,
            InputStream = stream,
            ContentType = request.ContentType
        };

        // Rely on bucket policy for public access; do not set ACLs to avoid conflicts with ACL-disabled buckets.
        await _s3.PutObjectAsync(putRequest, cancellationToken).ConfigureAwait(false);
        if (_logger.IsEnabled(LogLevel.Information))
        {

View on GitHub (pinned to 3f2959e683)