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
- Upload a smaller file or compress/resize it so the declared size is within category.MaxBytes.
- If the limit is too strict for real use, raise the category's MaxBytes in the Files options configuration.
- Fix client size computation to report true byte count (e.g. file.size from the browser File API).
- 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
- Check file.size in the browser before calling the API and show the limit in the UI.
- Report size with file.size (bytes) — never compute from MB approximations.
- Surface per-category limits to users in the upload dialog.
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
- Declared size must be positive.
- Unknown visibility value
- uploaded size ( ) exceeds declared ( )
- uploaded content-type mismatch
- Unknown category ' '.
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)