dotnet/aspnetcore · error · InvalidOperationException
The registered callback {registration.Callback.Method.Name}
Error message
The registered callback {registration.Callback.Method.Name} must be associated with a component or define an explicit render mode type during registration. What it means
Thrown by ComponentStatePersistenceManager.InferRenderModes when a registered persisting callback has RenderMode == null (no explicit render mode passed to RegisterOnPersisting) and its Callback.Target is not an IComponent, so the renderer cannot infer a render mode from an owning component. This matters only in multi-store (composite) scenarios - e.g. a Blazor Web App with InteractiveAuto - where the framework must route each callback to the correct store (Server vs WebAssembly).
Source
Thrown at src/Components/Components/src/PersistentState/ComponentStatePersistenceManager.cs:206
}
if (registration.Callback.Target is IComponent component)
{
var componentRenderMode = renderer.GetComponentRenderMode(component);
if (componentRenderMode != null)
{
_registeredCallbacks[i] = new PersistComponentStateRegistration(registration.Callback, componentRenderMode);
}
else
{
// If we can't find a render mode, it's an SSR only component and we don't need to
// persist its state at all.
_registeredCallbacks[i] = default;
}
continue;
}
throw new InvalidOperationException(
$"The registered callback {registration.Callback.Method.Name} must be associated with a component or define" +
$" an explicit render mode type during registration.");
}
}
internal Task<bool> TryPauseAsync(IPersistentComponentStateStore store)
{
List<Task<bool>>? pendingCallbackTasks = null;
// We are iterating backwards to allow the callbacks to remove themselves from the list.
// Otherwise, we would have to make a copy of the list to avoid running into situations
// where we don't run all the callbacks because the count of the list changed while we
// were iterating over it.
// It is not allowed to register a callback while we are persisting the state, so we don't
// need to worry about new callbacks being added to the list.
for (var i = _registeredCallbacks.Count - 1; i >= 0; i--)
{
var registration = _registeredCallbacks[i];View on GitHub (pinned to 294cab2f9b)
Solutions
- Pass an explicit render mode to RegisterOnPersisting, e.g. RegisterOnPersisting(callback, RenderMode.InteractiveWebAssembly) or InteractiveServer as appropriate.
- Register the callback from inside a component so its Target is the component and the render mode can be inferred.
- For persistent services, use [PersistentState] properties plus AddPersistentService<T> and specify the render mode at registration.
- If the callback genuinely belongs to no render mode, scope it to a single-store scenario instead of a composite store.
Example fix
// before (Auto render mode, service-based lambda) _state.RegisterOnPersisting(() => PersistMyService()); // after _state.RegisterOnPersisting(() => PersistMyService(), RenderMode.InteractiveWebAssembly);
Defensive patterns
Strategy: validation
Validate before calling
// When registering a persist callback from a non-component (service/lambda) target
// in a composite-store (Auto) app, always pass an explicit render mode:
PersistentComponentState RegisterPersist(PersistentComponentState state,
Func<Task> callback, IComponentRenderMode mode)
=> state.RegisterOnPersisting(callback, mode) is var _
? throw null! // placeholder; real usage below
: null!;
// Real usage:
// state.RegisterOnPersisting(PersistService, RenderMode.InteractiveWebAssembly); Prevention
- Always pass an explicit IComponentRenderMode when registering a service/lambda-based persist callback in Auto or multi-store apps.
- Register persist callbacks from inside a component when possible so inference works.
- For persistent services, use [PersistentState] + AddPersistentService<T> and specify render mode at registration.
- When upgrading a Server-only app to Auto, audit all service-based RegisterOnPersisting calls and add explicit render modes.
When it happens
Trigger: state.RegisterOnPersisting(callback) where callback is a lambda whose captured Target is a service or a static method (not a component), used in an app with multiple persistent state stores, without passing an explicit IComponentRenderMode.
Common situations: Persisting state from an injected service via a lambda (() => service.Persist()) in a Blazor Web App with global Auto interactivity; upgrading a Server-only app to Auto where an existing service-based callback now fails; registering a persist callback from a non-component host.
Related errors
- Cannot update existing state: previous state has not been cl
- State already initialized.
- State already persisted.
- Render mode already set.
- The type '{targetType.FullName}' declares a property matchin
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/4b1d3943572b7d54.
Report an issue: GitHub.