spectreconsole/spectre.console · error · InvalidOperationException

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

Error message

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

What it means

Thrown inside the spinner source generator when an AdditionalFiles entry ending in spinners_default.json matched but GetText returned null. The default spinner set is required (the generator returns an empty array if either default or sindresorhus data is missing, but the per-file read failure still throws first). It is a compile-time InvalidOperationException in the generator pipeline.

Source

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

/// </summary>
[Generator]
public class SpinnerGenerator : IIncrementalGenerator
{
    // UTF-8 without a BOM, matching the repository's source file convention
    // and keeping the checked-in generated files deterministic.
    private static readonly Encoding Utf8NoBom = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);

    /// <inheritdoc />
    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;

View on GitHub (pinned to 0acc92fada)

Solutions

  1. Clean rebuild (dotnet clean && dotnet build) to re-read AdditionalFiles
  2. Confirm spinners_default.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_default.json

Example fix

# before: spinners_default.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_default.json AdditionalFiles item resolves
dotnet msbuild -getItem:AdditionalFiles | findstr spinners_default.json

Prevention

When it happens

Trigger: The spinners_default.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_default.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/749f153ed20707ff. Report an issue: GitHub.