fullstackhero/dotnet-starter-kit · error · CustomException

File exceeds max size of

Error message

File exceeds max size of {category.MaxBytes} bytes for category '{cmd.Category}'.

What it means

CustomException (BadRequest) thrown when cmd.SizeBytes exceeds category.MaxBytes for the requested category. The handler pre-checks the declared size before issuing a presigned URL so oversized uploads never reach storage.

Solutions

  1. Upload a smaller file or compress/resize it so the declared size is within category.MaxBytes.
  2. If the limit is too strict for real use, raise the category's MaxBytes in the Files options configuration.
  3. Fix client size computation to report true byte count (e.g. file.size from the browser File API).
  4. Validate size client-side before calling the API and show the allowed maximum to the user.

Example fix

// before
await requestUploadUrl({ category: "avatar", sizeBytes: file.size, ... }); // file.size = 25_165_824 > 5 MB limit
// after
if (file.size > 5 * 1024 * 1024) showError("Max 5 MB");
await requestUploadUrl({ category: "avatar", sizeBytes: file.size, ... });
Defensive patterns

Strategy: validation

Validate before calling

if (file.size > category.maxBytes) throw new Error(`Max ${category.maxBytes} bytes for ${category.name}`);

Try / catch

try { await requestUploadUrl(cmd); } catch (e) { if (e.status === 400 && e.message?.includes("exceeds max size")) { showToast(`File too large — limit is ${e.maxBytes} bytes`); } else throw e; }

Prevention

When it happens

Trigger: RequestUploadUrlCommand whose client-declared SizeBytes is greater than the configured max for that category — e.g. a 20 MB file against a 5 MB avatar limit, or an int/byte-unit mistake where the client reports bytes but computed megabytes (or vice versa).

Common situations: Users selecting large images/videos for a size-capped category; client computing size incorrectly (MB vs MiB, bits vs bytes) and over-reporting; category MaxBytes lowered in config while clients still offer large files; reporting the compressed size while category limits assume another baseline.

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/c99d1c29c0cbafb3. Report an issue: GitHub.

Appendix: source

Thrown at src/Modules/Files/Modules.Files/Features/v1/RequestUploadUrl/RequestUploadUrlCommandHandler.cs:56

        // Category lookup + extension/size validation.
        if (!options.Value.Categories.TryGetValue(cmd.Category, out var category))
        {
            throw new CustomException($"Unknown category '{cmd.Category}'.", (IEnumerable<string>?)null, HttpStatusCode.BadRequest);
        }

        var extension = Path.GetExtension(cmd.FileName);
        if (string.IsNullOrWhiteSpace(extension) ||
            !category.AllowedExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
        {
            throw new CustomException(
                $"Extension '{extension}' not allowed for category '{cmd.Category}'.",
                (IEnumerable<string>?)null,
                HttpStatusCode.BadRequest);
        }

        if (cmd.SizeBytes > category.MaxBytes)
        {
            throw new CustomException(
                $"File exceeds max size of {category.MaxBytes} bytes for category '{cmd.Category}'.",
                (IEnumerable<string>?)null,
                HttpStatusCode.BadRequest);
        }

        // Authorization: policy must exist and allow the attach.
        var policy = policies.Resolve(cmd.OwnerType)
            ?? throw new ForbiddenException($"No file access policy registered for owner type '{cmd.OwnerType}'.");
        if (!await policy.CanAttachAsync(cmd.OwnerId, userId.ToString(), cancellationToken).ConfigureAwait(false))
        {
            throw new ForbiddenException("Not allowed to attach files to this owner.");
        }

        // Quota pre-check (no debit yet — debit happens on finalize with actual bytes).
        var quotaCheck = await quotas.CheckAsync(tenantId, QuotaResource.StorageBytes, cmd.SizeBytes, cancellationToken).ConfigureAwait(false);
        if (!quotaCheck.Allowed)
        {
            throw new CustomException(

View on GitHub (pinned to 3f2959e683)