microsoft/aspire · error

Historical dashboard data is read-only.

Error message

Historical dashboard data is read-only.

What it means

DashboardDataSource tracks historical (loaded-from-disk) dashboard data in a read-only mode. EnsureWritable throws InvalidOperationException when code attempts to mutate a data source that was opened read-only, i.e. IsReadOnly is true because the data represents a past run rather than the live one.

Solutions

  1. Check IsReadOnly before mutating and route writes to the current run's data source instead
  2. Obtain a writable (current-run) DashboardDataSource from the pool for live data operations
  3. If historical data legitimately must change (e.g. pinning), use the dedicated API (DashboardRunStore.SetRunPinned) rather than mutating the data source
Defensive patterns

Strategy: type-guard

Validate before calling

if (dataSource.IsReadOnly)
{
    // route write operations to the current run's data source instead
}

Type guard

bool IsWritable(DashboardDataSource source) => !source.IsReadOnly;

Try / catch

try
{
    source.EnsureWritable();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("read-only"))
{
    // fall back to the current run's writable data source
}

Prevention

When it happens

Trigger: Calling EnsureWritable() (directly or via APIs that require a writable data source, e.g. adding telemetry or updating run state) on a DashboardDataSource whose IsReadOnly property is true — typically a historical run loaded from a persisted database.

Common situations: Writing telemetry or selection state into a historical run's data source opened from disk; a component that assumed it held the current run's data source but actually resolved a historical one from the pool.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at src/Aspire.Dashboard/ServiceClient/DashboardDataSource.cs:72

    internal DashboardRunDescriptor SelectedRun { get; private set; } = null!;

    /// <summary>
    /// Gets the telemetry repository for the selected dashboard run.
    /// </summary>
    public ITelemetryRepository TelemetryRepository { get; private set; } = null!;

    /// <summary>
    /// Gets the resource repository for the selected dashboard run.
    /// </summary>
    public IResourceRepository ResourceRepository { get; private set; } = null!;

    internal bool IsReadOnly { get; private set; }

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

    DashboardRunDescriptor IDashboardRunSelection.SelectedRun => SelectedRun;

    void IDashboardRunSelection.SelectRun(string? runId) => SelectRun(runId);

    internal void SelectRun(string? runId)
    {
        var currentRun = _runStore.GetCurrentRun();
        var selectedRun = runId is not null ? _runStore.GetRunById(runId, onlyCompatible: true) : null;
        if (selectedRun is null)
        {
            if (!string.IsNullOrEmpty(runId))
            {
                _logger.LogWarning("Failed to switch to dashboard run '{RunId}' because it is no longer available.", runId);
            }

View on GitHub (pinned to 25830f84bd)