microsoft/aspire · error
Dashboard run metadata for
Error message
Dashboard run metadata for '{run.RunId}' is invalid. What it means
UpdatePinnedState reads the run's run.json metadata and validates it before rewriting the pinned flag. It throws InvalidDataException when the deserialized metadata is null, its SchemaVersion differs from the in-memory run descriptor's, or its RunId doesn't match — i.e. the on-disk metadata doesn't correspond to the run being updated.
Solutions
- Restore or regenerate the run.json file so its SchemaVersion and RunId match the run being pinned
- Remove the corrupted historical run directory and let the dashboard recreate consistent state
- Do not hand-edit run metadata; change pinned state through the dashboard or SetRunPinned API
Example fix
// before: hand-edited run.json breaks the pin operation
// after: verify metadata before pinning
var meta = JsonSerializer.Deserialize<DashboardRunMetadata>(File.ReadAllText(Path.Combine(runDir, "run.json")));
if (meta is null || meta.RunId != run.RunId || meta.SchemaVersion != run.SchemaVersion)
{
throw new InvalidDataException($"Corrupt run metadata for '{run.RunId}'; delete or restore the run directory.");
} Defensive patterns
Strategy: validation
Validate before calling
var metaPath = Path.Combine(runDirectory, "run.json");
if (!File.Exists(metaPath)) return false;
try
{
var meta = JsonSerializer.Deserialize<DashboardRunMetadata>(File.ReadAllText(metaPath));
return meta is not null && meta.RunId == run.RunId && meta.SchemaVersion == run.SchemaVersion;
}
catch (JsonException)
{
return false;
} Try / catch
try
{
store.SetRunPinned(run, isPinned: true);
}
catch (InvalidDataException ex) when (ex.Message.Contains("is invalid"))
{
// quarantine/delete the corrupted run directory
} Prevention
- Never hand-edit run.json or copy it between run directories
- Recreate run directories after crashes that may leave partial metadata
- After dashboard upgrades, verify persisted metadata SchemaVersion before mutating runs
When it happens
Trigger: Pinning a run whose run.json is missing, corrupt JSON, hand-edited, or was written by a different dashboard version (SchemaVersion mismatch) or belongs to a different RunId.
Common situations: Manually editing or copying run.json between run directories; a partially-written/corrupted metadata file after a crash; upgrading the dashboard so the persisted SchemaVersion no longer matches; deleting/renaming run directories by hand.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- Dashboard database for run
- Dashboard run ' ' is no longer available.
- Dashboard run ' ' is no longer available.
- Error deserializing GenAI message content. Error description
- Expected a JSON array.
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/af21cb4bc0a9046e.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Dashboard/ServiceClient/DashboardRunStore.cs:307
{
// The current run has the store's lifetime lock, and a selected historical run has a lease.
// Only an unselected historical run needs a temporary lock while its metadata is updated.
using var runLock = storedRun.IsCurrent || storedRun.IsLeased
? null
: TryOpenRunLock(runDirectory)
?? throw new InvalidOperationException($"Dashboard run '{storedRun.RunId}' is no longer available.");
UpdatePinnedState(storedRun, runDirectory, isPinned);
}
}
private void UpdatePinnedState(DashboardRunDescriptor run, string runDirectory, bool isPinned)
{
var metadataPath = Path.Combine(runDirectory, "run.json");
var metadata = JsonSerializer.Deserialize<DashboardRunMetadata>(File.ReadAllText(metadataPath));
if (metadata?.SchemaVersion != run.SchemaVersion ||
!string.Equals(metadata.RunId, run.RunId, StringComparison.Ordinal))
{
throw new InvalidDataException($"Dashboard run metadata for '{run.RunId}' is invalid.");
}
var updatedMetadata = metadata with { IsPinned = isPinned };
WriteMetadata(updatedMetadata, metadataPath);
if (string.Equals(run.RunId, RunId, StringComparison.Ordinal))
{
_metadata = updatedMetadata;
}
run.IsPinned = isPinned;
}
public void PublishRun()
{
if (_metadataPath is null || _metadataPublished)
{
return;
}View on GitHub (pinned to 25830f84bd)