dotnet/aspnetcore · error · InvalidOperationException

The value of {nameof(IsFixed)} cannot be changed dynamically

Error message

The value of {nameof(IsFixed)} cannot be changed dynamically.

What it means

Thrown by CascadingValue<TValue>.SetParametersAsync when IsFixed differs from the value used in a previous parameter set. The framework caches subscriber-notification behavior based on IsFixed at first delivery, so toggling it mid-lifecycle would corrupt the subscription model. Once a CascadingValue is created with a given IsFixed, it must keep that value for all subsequent renders.

Source

Thrown at src/Components/Components/src/CascadingValue.cs:96

                Name = (string)parameter.Value;
                if (string.IsNullOrEmpty(Name))
                {
                    throw new ArgumentException($"The parameter '{nameof(Name)}' for component '{nameof(CascadingValue<TValue>)}' does not allow null or empty values.");
                }
            }
            else if (parameter.Name.Equals(nameof(IsFixed), StringComparison.OrdinalIgnoreCase))
            {
                IsFixed = (bool)parameter.Value;
            }
            else
            {
                throw new ArgumentException($"The component '{nameof(CascadingValue<TValue>)}' does not accept a parameter with the name '{parameter.Name}'.");
            }
        }

        if (_hasSetParametersPreviously && IsFixed != previousFixed)
        {
            throw new InvalidOperationException($"The value of {nameof(IsFixed)} cannot be changed dynamically.");
        }

        _hasSetParametersPreviously = true;

        // It's OK for the value to be null, but some "Value" param must be supplied
        // because it serves no useful purpose to have a <CascadingValue> otherwise.
        if (!hasSuppliedValue)
        {
            throw new ArgumentException($"Missing required parameter '{nameof(Value)}' for component '{GetType().Name}'.");
        }

        // Rendering is most efficient when things are queued from rootmost to leafmost.
        // Given a components A (parent) -> B (child), you want them to be queued in order
        // [A, B] because if you had [B, A], then the render for A might change B's params
        // making it render again, so you'd render [B, A, B], which is wasteful.
        // At some point we might consider making the render queue actually enforce this
        // ordering during insertion.
        //

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Decide IsFixed at component creation and keep it constant for the component's lifetime.
  2. If you need dynamic updates, set IsFixed=false from the start (it just costs a small subscription overhead).
  3. If the value truly never changes, set IsFixed=true once and leave it.

Example fix

// before
<CascadingValue Value="@_data" IsFixed="@_isLoaded">
    <Child />
</CascadingValue>
@code { private bool _isLoaded = false; /* flips to true later */ }

// after
<CascadingValue Value="@_data" IsFixed="false">
    <Child />
</CascadingValue>
Defensive patterns

Strategy: validation

Validate before calling

// Keep IsFixed constant across renders — verify before re-render
if (_hasSetParametersPreviously && IsFixed != _previousFixed)
    throw new InvalidOperationException("IsFixed cannot change.");

Prevention

When it happens

Trigger: Binding IsFixed to a value that changes between renders, e.g., <CascadingValue IsFixed="@_isFixedFlag"> where _isFixedFlag toggles. The check compares against previousFixed at CascadingValue.cs:94-97.

Common situations: Conditionally setting IsFixed based on data that loads asynchronously; refactoring code where IsFixed was a literal and is later bound to a variable that changes.

Related errors


AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06). Data as JSON: /api/errors/f2e6dffa20eaa281. Report an issue: GitHub.