dotnet/aspnetcore · error · InvalidOperationException
The ParameterView instance can no longer be read because it
Error message
The ParameterView instance can no longer be read because it has expired. ParameterView can only be read synchronously and must not be stored for later use.
What it means
ParameterView is a read-only view over a mutable internal buffer used during parameter assignment. The buffer is reused across renders, so reading a ParameterView after the synchronous SetParametersAsync phase risks reading stale or overwritten data. ParameterViewLifetime stamps the view at creation and checks the stamp on every read; if the underlying buffer's stamp has changed (because a new render batch started), it throws InvalidOperationException.
Source
Thrown at src/Components/Components/src/Rendering/ParameterViewLifetime.cs:25
{
private readonly RenderBatchBuilder _owner;
private readonly int _stamp;
public static readonly ParameterViewLifetime Unbound;
public ParameterViewLifetime(RenderBatchBuilder owner)
{
_owner = owner;
_stamp = owner.ParameterViewValidityStamp;
}
public void AssertNotExpired()
{
// If _owner is null, this instance is default(ParameterViewLifetime), which is
// the same as ParameterViewLifetime.Unbound. That means it never expires.
if (_owner != null && _owner.ParameterViewValidityStamp != _stamp)
{
throw new InvalidOperationException($"The {nameof(ParameterView)} instance can no longer be read because it has expired. {nameof(ParameterView)} can only be read synchronously and must not be stored for later use.");
}
}
}
View on GitHub (pinned to 294cab2f9b)
Solutions
- Extract all needed values from ParameterView synchronously at the top of SetParametersAsync, before any await, and store those values in fields.
- Never store the ParameterView itself; copy individual parameter values out immediately.
- If you need to read parameters asynchronously, capture the values into local variables before awaiting.
- For deferred logic, pass extracted values (strings, ints, etc.) to the deferred code, never the ParameterView.
Example fix
// before
public override async Task SetParametersAsync(ParameterView parameters)
{
await SomeAsyncWork();
var name = parameters.TryGetValue<string>("Name", out var n) ? n : null; // throws: expired
}
// after
public override async Task SetParametersAsync(ParameterView parameters)
{
var name = parameters.TryGetValue<string>("Name", out var n) ? n : null;
await SomeAsyncWork(); // read parameters first
} Defensive patterns
Strategy: validation
Validate before calling
// Extract all parameter values synchronously at the top of SetParametersAsync
public override Task SetParametersAsync(ParameterView parameters)
{
// Read everything BEFORE any await
_name = parameters.TryGetValue<string>("Name", out var n) ? n : null;
_count = parameters.TryGetValue<int>("Count", out var c) ? c : 0;
return base.SetParametersAsync(parameters);
} Type guard
null // ParameterView is a struct; no type guard applies. The guard is procedural: read synchronously.
Prevention
- Never store ParameterView in a field; extract primitive values immediately.
- Read all parameters at the top of SetParametersAsync, before any await.
- Use a Roslyn analyzer or code review checklist to flag deferred ParameterView access.
- In async methods, capture needed values into locals before the first await.
When it happens
Trigger: Storing a ParameterView in a field or capturing it in a closure, then reading it later. Common triggers: reading parameters after an await in SetParametersAsync (the buffer may be recycled during the async gap); saving ParameterView for use in OnAfterRenderAsync or an event handler; passing ParameterView to a background task.
Common situations: Async SetParametersAsync that reads ParameterView after await Task.Yield() or an I/O call; storing ParameterView in a field to defer reading; capturing ParameterView in a timer callback or event subscription; misunderstanding that ParameterView is a transient view, not a snapshot.
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
- The current dispatcher does not support synchronous calls fr
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/5d9cf3cf3f912a6e.
Report an issue: GitHub.