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
- Decide IsFixed at component creation and keep it constant for the component's lifetime.
- If you need dynamic updates, set IsFixed=false from the start (it just costs a small subscription overhead).
- 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
- Use a literal or constant for IsFixed, not a dynamic binding.
- Default to IsFixed=false if unsure — it's always safe, just slightly less optimal.
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
- Interop methods are already registered for renderer ${render
- Interop methods are not registered for renderer ${rendererId
- No interop methods are registered for renderer ${rendererId}
- Renderer with ID '${rendererId}' is not listening for naviga
- JS object instance with ID ${targetInstanceId} does not exis
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/f2e6dffa20eaa281.
Report an issue: GitHub.