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

  1. Restore or regenerate the run.json file so its SchemaVersion and RunId match the run being pinned
  2. Remove the corrupted historical run directory and let the dashboard recreate consistent state
  3. 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

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


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)