spectreconsole/spectre.console · error · InvalidOperationException

Failed to read spinners_sindresorhus.json at {file.Path}

Error message

Failed to read spinners_sindresorhus.json at {file.Path}

What it means

Thrown inside the spinner source generator when an AdditionalFiles entry ending in spinners_sindresorhus.json matched but GetText returned null. Same shape as the default-spinner read failure; it surfaces as a compile-time InvalidOperationException in the generator pipeline.

Source

Thrown at src/Spectre.Console.SourceGenerator/Spinners/SpinnerGenerator.cs:38

    public void Initialize(IncrementalGeneratorInitializationContext context)
    {
        // Find spinners_default.json
        // Step 1: Extract text (cached by string value equality)
        // Step 2: Wrap in EquatableArray for value equality when combining
        var defaultSpinners = context.AdditionalTextsProvider
            .Where(static file => file.Path.EndsWith("spinners_default.json", StringComparison.OrdinalIgnoreCase))
            .Select(static (file, ct) =>
                file.GetText(ct)?.ToString()
                ?? throw new InvalidOperationException($"Failed to read spinners_default.json at {file.Path}"))
            .Collect()
            .Select(static (arr, _) => new EquatableArray<string>(arr));

        // Find spinners_sindresorhus.json
        var sindreSpinners = context.AdditionalTextsProvider
            .Where(static file => file.Path.EndsWith("spinners_sindresorhus.json", StringComparison.OrdinalIgnoreCase))
            .Select(static (file, ct) =>
                file.GetText(ct)?.ToString()
                ?? throw new InvalidOperationException($"Failed to read spinners_sindresorhus.json at {file.Path}"))
            .Collect()
            .Select(static (arr, _) => new EquatableArray<string>(arr));

        // Combine both JSON files and parse in the pipeline (for caching)
        // EquatableArray has value equality, so this step is properly cached
        var spinners = defaultSpinners.Combine(sindreSpinners)
            .Select(static (data, _) =>
            {
                var (defaultJsonFiles, sindreJsonFiles) = data;
                if (defaultJsonFiles.IsEmpty || sindreJsonFiles.IsEmpty)
                {
                    return EquatableArray<SpinnerModel>.Empty;
                }

                var parsedSpinners = SpinnerParser.ParseAll(defaultJsonFiles[0], sindreJsonFiles[0]);
                var validSpinners = parsedSpinners
                    .Where(IsValidSpinner)
                    .ToArray();

View on GitHub (pinned to 0acc92fada)

Solutions

  1. Clean rebuild (dotnet clean && dotnet build) to re-read AdditionalFiles
  2. Confirm spinners_sindresorhus.json exists and is readable on disk
  3. Restore/reinstall the Spectre.Console package to refresh the file
  4. Release any process lock on spinners_sindresorhus.json

Example fix

# before: spinners_sindresorhus.json unreadable during generation
# after: clean generation
dotnet clean
dotnet restore
dotnet build
Defensive patterns

Strategy: validation

Validate before calling

// Pre-build check: confirm spinners_sindresorhus.json AdditionalFiles item resolves
dotnet msbuild -getItem:AdditionalFiles | findstr spinners_sindresorhus.json

Prevention

When it happens

Trigger: The spinners_sindresorhus.json AdditionalFiles item is in the graph but its text cannot be read at generation time (locked, deleted mid-build, unreadable, empty).

Common situations: Corrupted spinners_sindresorhus.json; antivirus/IDE lock; partial checkout; package restore that left the file missing or zero-byte.

Related errors


AI-assisted analysis of spectreconsole/spectre.console@0acc92fada (2026-08-13). Data as JSON: /api/errors/d116e8b33a3f80dc. Report an issue: GitHub.