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
- Check IsReadOnly before mutating and route writes to the current run's data source instead
- Obtain a writable (current-run) DashboardDataSource from the pool for live data operations
- 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
- Check IsReadOnly before any mutation of historical data
- Keep references to historical and current data sources clearly separated
- Use dedicated store APIs (e.g. SetRunPinned) for historical state changes
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
- Historical dashboard data is read-only.
- Dashboard resource is not initialized
- Already connected to
- AppHost:ResourceService:ApiKey is not specified in…
- [aspire-terminal] WS closed abnormally
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)