microsoft/aspire · error · InvalidOperationException

Historical dashboard data is read-only.

Error message

Historical dashboard data is read-only.

What it means

SelectedDashboardClient wraps the live dashboard backend; when the session is in read-only (historical) mode, mutating operations must not run. EnsureWritable is called by mutating APIs (ClearConsoleLogsAsync, SendInteractionRequestAsync, ExecuteResourceCommandAsync, UploadFileAsync) and throws this InvalidOperationException when IsReadOnly is true. Historical data views are intentionally immutable.

Solutions

  1. Check IsReadOnly before issuing any mutating call and no-op or prompt the user instead
  2. Reconnect the dashboard client to a live session to perform commands or uploads
  3. Restrict mutation entry points in UI so they are disabled in historical mode

Example fix

// before
await client.ExecuteResourceCommandAsync(command);
// after
if (!client.IsReadOnly)
{
    await client.ExecuteResourceCommandAsync(command);
}
Defensive patterns

Strategy: validation

Validate before calling

if (client.IsReadOnly)
{
    return; // historical sessions are immutable
}

Try / catch

try { await client.ExecuteResourceCommandAsync(cmd); }
catch (InvalidOperationException ex) when (ex.Message.Contains("read-only"))
{
    logger.LogWarning("Cannot mutate historical dashboard data");
}

Prevention

When it happens

Trigger: Calling ExecuteResourceCommandAsync, ClearConsoleLogsAsync, SendInteractionRequestAsync, or UploadFileAsync on a SelectedDashboardClient whose session targets historical/archived data (IsReadOnly == true).

Common situations: Dashboard tooling or extensions operating against a historical data view (e.g. viewing archived logs from a previous session) and invoking commands or uploads that only make sense on a live session.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/e47d8594a70fc39d. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Dashboard/ServiceClient/SelectedDashboardClient.cs:77

    }

    public Task<ResourceCommandResponseViewModel> ExecuteResourceCommandAsync(string resourceName, string resourceType, CommandViewModel command, ExecuteResourceCommandOptions options, CancellationToken cancellationToken)
    {
        EnsureWritable();
        return currentClient.ExecuteResourceCommandAsync(resourceName, resourceType, command, options, cancellationToken);
    }

    public Task<string> UploadFileAsync(Stream fileStream, string fileName, long expectedSize, int interactionId, string inputName, CancellationToken cancellationToken)
    {
        EnsureWritable();
        return currentClient.UploadFileAsync(fileStream, fileName, expectedSize, interactionId, inputName, cancellationToken);
    }

    private void EnsureWritable()
    {
        if (IsReadOnly)
        {
            throw new InvalidOperationException("Historical dashboard data is read-only.");
        }
    }

    private static async IAsyncEnumerable<WatchInteractionsResponseUpdate> EmptyInteractionsAsync()
    {
        await Task.CompletedTask.ConfigureAwait(false);
        yield break;
    }

    public ValueTask DisposeAsync() => ValueTask.CompletedTask;
}

View on GitHub (pinned to 25830f84bd)