{"record":{"id":"1e4800909ffe26cc","repo":"microsoft/aspire","slug":"file-filename-exceeded-the-expected-size-of-expectedsize","errorCode":null,"errorMessage":"File '{fileName}' exceeded the expected size of {expectedSize} bytes.","messagePattern":"File '(.+?)' exceeded the expected size of (.+?) bytes\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/Aspire.Dashboard/ServiceClient/DashboardClient.cs","lineNumber":1126,"sourceCode":"    public async Task<string> UploadFileAsync(Stream fileStream, string fileName, long expectedSize, int interactionId, string inputName, CancellationToken cancellationToken)\n    {\n        EnsureInitialized();\n\n        using var combinedTokens = CancellationTokenSource.CreateLinkedTokenSource(_clientCancellationToken, cancellationToken);\n        using var call = _client!.UploadFile(headers: _headers, cancellationToken: combinedTokens.Token);\n\n        const int chunkSize = 64 * 1024; // 64 KB chunks\n        var buffer = new byte[chunkSize];\n        var isFirst = true;\n        long totalBytesRead = 0;\n\n        int bytesRead;\n        while ((bytesRead = await fileStream.ReadAsync(buffer, combinedTokens.Token).ConfigureAwait(false)) > 0)\n        {\n            totalBytesRead += bytesRead;\n            if (totalBytesRead > expectedSize)\n            {\n                throw new InvalidOperationException($\"File '{fileName}' exceeded the expected size of {expectedSize} bytes.\");\n            }\n\n            var chunk = new UploadFileChunk\n            {\n                Data = Google.Protobuf.ByteString.CopyFrom(buffer, 0, bytesRead)\n            };\n\n            if (isFirst)\n            {\n                chunk.FileName = fileName;\n                chunk.InteractionId = interactionId;\n                chunk.InputName = inputName;\n            }\n\n            await call.RequestStream.WriteAsync(chunk, combinedTokens.Token).ConfigureAwait(false);\n            isFirst = false;\n        }\n","sourceCodeStart":1108,"sourceCodeEnd":1144,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Dashboard/ServiceClient/DashboardClient.cs#L1108-L1144","documentation":"DashboardClient validates file upload size while streaming chunks to the dashboard service over gRPC. The library throws this InvalidOperationException as soon as cumulative bytes read from the file exceed the expected size recorded when the upload was initiated, preventing oversized or concurrently-modified files from being silently uploaded. It is a safety check against the file changing between size measurement and streaming.","triggerScenarios":"Calling the dashboard client's file upload API when the on-disk file grows (or was measured incorrectly) after its size was computed: totalBytesRead exceeds expectedSize during the ReadAsync loop.","commonSituations":"A log file or trace file is still being appended to by the application while it is being uploaded; the file was swapped or truncated/expanded between the size query and the stream read; uploading a live-growing artifact in a shared directory.","solutions":["Stop writing to the file (or take a snapshot/copy) before starting the upload, then retry the upload","Re-measure the file size immediately before the upload so expectedSize matches current content","Retry the upload after the file stabilizes; if the file is legitimately larger, initiate a new upload with the new expected size"],"exampleFix":"// before: upload a file while the app still appends to it\nawait client.UploadFileAsync(liveLogPath);\n\n// after: snapshot the file first so size and content cannot diverge\nvar snapshotPath = Path.Combine(tempDir, Path.GetFileName(liveLogPath));\nFile.Copy(liveLogPath, snapshotPath, overwrite: true);\nawait client.UploadFileAsync(snapshotPath);","handlingStrategy":"validation","validationCode":"var fileInfo = new FileInfo(path);\nif (!fileInfo.Exists || fileInfo.Length == 0)\n{\n    throw new FileNotFoundException(path);\n}\n// ensure the file is not actively growing before uploading\nawait Task.Delay(500); // optional stability check\nif (new FileInfo(path).Length != fileInfo.Length)\n{\n    // file is still being written; snapshot or wait before upload\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    await UploadFileAsync(path);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"exceeded the expected size\"))\n{\n    // re-snapshot and retry with a fresh expected size\n}","preventionTips":["Snapshot files to stable temp storage before uploading","Recompute expected size immediately before upload","Stop producers from appending to a file during upload"],"tags":["file-upload","grpc","dashboard","size-validation"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T09:17:21.228Z"}