microsoft/aspire · error · InvalidOperationException
An interaction ID is required when uploading a file.
Error message
An interaction ID is required when uploading a file.
What it means
UploadFileAsync requires the upload to be associated with an active interaction; it throws InvalidOperationException when request.InteractionId is zero or negative. The uploaded file must be attached to a pending file-upload interaction identified by that id.
Solutions
- Set InteractionId to the id of the pending file-upload interaction that requested the file.
- Only call UploadFileAsync from within the interaction callback where the interaction id is available.
- Verify the id was copied correctly from the interaction payload (not left at the default 0).
Example fix
// before
await rpc.UploadFileAsync(new UploadFileRequest { FileName = f, Data = bytes }); // InteractionId = 0
// after
await rpc.UploadFileAsync(new UploadFileRequest { FileName = f, Data = bytes, InteractionId = interaction.Id, InputName = "file" }); Defensive patterns
Strategy: validation
Validate before calling
if (request.InteractionId <= 0)
{
throw new InvalidOperationException("Set InteractionId from the pending file-upload interaction before uploading.");
} Type guard
static bool HasInteractionId(UploadFileRequest r) => r.InteractionId > 0;
Try / catch
try
{
await rpc.UploadFileAsync(request, cancellationToken);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("interaction ID is required"))
{
// rebuild the request with the active interaction's id
} Prevention
- Only build UploadFileRequest inside the file-upload interaction callback where the id is in scope.
- Never rely on the default InteractionId of 0; copy it explicitly from the interaction object.
When it happens
Trigger: Calling UploadFileAsync with a request whose InteractionId was never set (default 0) or is a stale/negative value — e.g., constructing UploadFileRequest without an interaction context.
Common situations: Uploading a file outside of an actual file-upload interaction flow; reusing a request object whose interaction id field defaulted to 0; an interaction that already completed so the stored id is no longer valid/positive in caller state.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- An input name is required when uploading a file.
- -32000
- Already connected to AppHost backchannel.
- AppHost server process exited before the RPC connection…
- callback ID missing
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/d4e2f1473048282e.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting/Backchannel/AppHostRpcTarget.cs:263
await activityReporter.CompleteInteractionAsync(promptId, answers, updateResponse: true, cancellationToken).ConfigureAwait(false);
}
/// <summary>
/// Registers a local file in the upload store by copying it to a managed temp location.
/// Returns the file ID that can be used to reference the file in interaction responses.
/// </summary>
public async Task<UploadFileResponse> UploadFileAsync(UploadFileRequest request, CancellationToken cancellationToken = default)
{
var maxUploadSize = FileUploadHelpers.GetMaxFileUploadSize(configuration);
if (request.Data.Length > maxUploadSize)
{
throw new InvalidOperationException($"File '{request.FileName}' exceeds the maximum upload size of {maxUploadSize} bytes.");
}
if (request.InteractionId <= 0)
{
throw new InvalidOperationException("An interaction ID is required when uploading a file.");
}
if (string.IsNullOrEmpty(request.InputName))
{
throw new InvalidOperationException("An input name is required when uploading a file.");
}
var (fileId, filePath) = fileUploadStore.CreateEntry(request.FileName, request.InteractionId, request.InputName);
try
{
var destStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 81920, useAsync: true);
await using (destStream.ConfigureAwait(false))
{
await destStream.WriteAsync(request.Data, cancellationToken).ConfigureAwait(false);
}
}
catch
{View on GitHub (pinned to 25830f84bd)