fullstackhero/dotnet-starter-kit · error · ArgumentOutOfRangeException
Actual size must be positive.
Error message
Actual size must be positive.
What it means
MarkAvailable validates that the actual size reported after upload is > 0 and throws ArgumentOutOfRangeException otherwise. A zero/negative actual size means the stored blob is empty or the size was misreported, which would corrupt quota accounting and download semantics.
Solutions
- Verify on the client that the uploaded blob size matches before calling complete; re-PUT the file if size is 0.
- Confirm the storage key used for the size probe is the same key the client uploaded to.
- Block zero-byte files at selection time in the UI.
- If the provider reports 0 after a successful PUT, check MinIO/S3 configuration (multipart completion, bucket policy).
Example fix
// before
await putToPresignedUrl(file);
await api.post(`/files/${id}/complete`); // may 500/422: actual size 0
// after
await putToPresignedUrl(file);
if (file.size <= 0) { showError('empty file'); return; }
await api.post(`/files/${id}/complete`); Defensive patterns
Strategy: validation
Validate before calling
if (!file || file.size <= 0) { showError('empty file'); return; }
await putToPresignedUrl(file); Prevention
- Verify uploaded blob size matches File.size before completing
- Block zero-byte files at selection
- Ensure the storage probe uses the same key the client uploaded to
When it happens
Trigger: Completing an upload where the storage object is 0 bytes (client PUT an empty body, partial/multipart upload failed silently), or the provider-reported ETag/size lookup returned 0.
Common situations: Client aborted the PUT halfway leaving an empty object; wrong storage key passed to the stat call so the size read defaults to 0; uploading an empty file that passed (or bypassed) the declared-size check.
Related errors
- Declared size must be positive.
- Cannot finalize file in status
- file not found
- upload not received
- uploaded size ( ) exceeds declared ( )
AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15).
Data as JSON: /api/errors/e7cd1ac2c5493e64.
Report an issue: GitHub.
Appendix: source
Thrown at src/Modules/Files/Modules.Files/Domain/FileAsset.cs:94
ScanStatus = ScanStatus.NotScanned,
UploadDeadline = uploadDeadline,
CreatedByUserId = createdByUserId,
CreatedAtUtc = DateTime.UtcNow
};
}
public void MarkAvailable(long actualSize, ScanStatus scanResult)
{
if (Status != FileAssetStatus.PendingUpload)
{
throw new CustomException(
$"Cannot finalize file in status {Status}.",
errors: null,
HttpStatusCode.Conflict);
}
if (actualSize <= 0)
{
throw new ArgumentOutOfRangeException(nameof(actualSize), "Actual size must be positive.");
}
SizeBytes = actualSize;
ScanStatus = scanResult;
Status = scanResult == ScanStatus.Infected ? FileAssetStatus.Quarantined : FileAssetStatus.Available;
UploadDeadline = null;
UpdatedAtUtc = DateTime.UtcNow;
AddDomainEvent(DomainEvent.Create((id, ts) =>
new FileFinalizedDomainEvent(Id, OwnerType, OwnerId, Status, id, ts)));
}
/// <summary>Reverses a soft delete. Idempotent.</summary>
public void Restore()
{
if (!IsDeleted) return;
IsDeleted = false;
DeletedOnUtc = null;View on GitHub (pinned to 3f2959e683)