microsoft/aspire · error · RpcException

ResourceExhausted

ResourceExhausted

Error message

Upload exceeds maximum allowed size of {maxTotalUploadBytes} bytes.

What it means

UploadFile enforces a total upload size cap of maxTotalUploadBytes. As chunks accumulate, once totalBytesWritten exceeds the cap an RpcException with StatusCode.ResourceExhausted is thrown and the upload is rejected, protecting the AppHost from unbounded temp-file growth.

Solutions

  1. Upload a smaller file or compress/truncate the data before uploading.
  2. Raise the maximum by adjusting the upload size limit configuration for the AppHost/resource service if your scenario legitimately needs larger files.
  3. Chunk and send only the needed portion (e.g. last N bytes of a log) instead of the whole file.
  4. Handle the ResourceExhausted status in the client and surface a friendly size-limit message to users.

Example fix

// before
await foreach (var b in ReadWholeFile(path)) stream.RequestStream.WriteAsync(new UploadFileChunk { Data = b });
// after
const long maxUpload = 10 * 1024 * 1024;
if (new FileInfo(path).Length > maxUpload)
{
    throw new InvalidOperationException($"File exceeds the {maxUpload} byte upload limit; compress or trim it first.");
}
Defensive patterns

Strategy: try-catch

Validate before calling

var length = new FileInfo(path).Length;
const long maxUploadBytes = 10 * 1024 * 1024; // match the service's configured limit
if (length > maxUploadBytes) throw new InvalidOperationException($"File of {length} bytes exceeds the {maxUploadBytes} byte upload limit.");

Try / catch

try { await uploadTask; } catch (RpcException ex) when (ex.StatusCode == StatusCode.ResourceExhausted) { logger.LogWarning("Upload rejected: {Detail}", ex.Status.Detail); /* surface size-limit message to user */ }

Prevention

When it happens

Trigger: Streaming an upload whose cumulative Data bytes across all chunks exceed the configured maximum (e.g. a very large log or data file uploaded through a dashboard file input).

Common situations: Users selecting oversized files in a dashboard file input; automated clients streaming large blobs; a misconfigured or default upload limit smaller than expected.

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 microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/6fe8e6fe5df8f56a. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting/Dashboard/DashboardService.cs:550

                    string path;
                    interactionId = chunk.InteractionId;
                    try
                    {
                        (fileId, path) = fileUploadStore.CreateEntry(chunk.FileName, interactionId.Value, chunk.InputName);
                    }
                    catch (InvalidOperationException ex)
                    {
                        throw new RpcException(new Status(StatusCode.FailedPrecondition, ex.Message));
                    }
                    fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 81920, useAsync: true);
                }

                if (!chunk.Data.IsEmpty)
                {
                    totalBytesWritten += chunk.Data.Length;
                    if (totalBytesWritten > maxTotalUploadBytes)
                    {
                        throw new RpcException(new Status(StatusCode.ResourceExhausted, $"Upload exceeds maximum allowed size of {maxTotalUploadBytes} bytes."));
                    }

                    await fileStream.WriteAsync(chunk.Data.Memory, cancellationToken).ConfigureAwait(false);
                }
            }

            if (fileStream is null)
            {
                throw new RpcException(new Status(StatusCode.InvalidArgument, "Upload stream is empty."));
            }

            // Close and flush the file before marking the upload complete. If disposal fails,
            // the catch path removes the entry so a partial upload is never retained.
            await fileStream.DisposeAsync().ConfigureAwait(false);
            fileStream = null;

            fileUploadStore.CompleteUpload(interactionId!.Value, fileId!);

View on GitHub (pinned to 25830f84bd)