dotnet/aspnetcore · error
initialParameters must be an object, even if empty.
Error message
initialParameters must be an object, even if empty.
What it means
Thrown by RootComponentsFunctions.add when initialParameters is null or undefined. The type ComponentParameters = object | null | undefined permits those in the signature, but the runtime requires an actual object so the framework can iterate parameter keys. Passing nothing or null is treated as a programmer error, not an empty-parameter intent.
Solutions
- Pass an empty object literal: {} when there are no parameters.
- Default the variable: const params = config?.params ?? {}.
- Add a type guard before calling add if parameters come from an untrusted source.
Example fix
// before (throws)
await Blazor.rootComponents.add(hostEl, 'MyComponent', null);
// after
await Blazor.rootComponents.add(hostEl, 'MyComponent', {});
// or with defaults
await Blazor.rootComponents.add(hostEl, 'MyComponent', params ?? {}); Defensive patterns
Strategy: type-guard
Validate before calling
const params = initialParameters ?? {};
if (typeof params !== 'object' || params === null || Array.isArray(params)) {
throw new Error('initialParameters must be a plain object.');
}
await Blazor.rootComponents.add(el, id, params); Type guard
function isPlainObject(v: unknown): v is Record<string, unknown> {
return typeof v === 'object' && v !== null && !Array.isArray(v);
} Prevention
- Default parameters to {} at the call site.
- Type the parameter as Record<string, unknown> rather than allowing null.
- Validate external config before passing it through.
When it happens
Trigger: Calling Blazor.rootComponents.add(element, 'MyComponent', null); calling with undefined because a variable was not initialized; forgetting the third argument.
Common situations: Dynamic root component registration where the component legitimately has no parameters and the developer passes null as 'empty'; reading parameters from a config source that returned null.
Related errors
- assembly must be defined when using a descriptor.
- Cannot have empty query parameter names.
- Cannot merge mismatching component descriptors
- Could not resolve a root component with SSR component ID
- descriptor must be defined when using a descriptor.
AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11).
Data as JSON: /api/errors/f7abcc2f79e9766e.
Report an issue: GitHub.
Appendix: source
Thrown at src/Components/Web.JS/src/Rendering/JSRootComponents.ts:21
import { DotNet } from '@microsoft/dotnet-js-interop';
const pendingRootComponentContainerNamePrefix = '__bl-dynamic-root:';
const pendingRootComponentContainers = new Map<string, Element>();
let nextPendingDynamicRootComponentIdentifier = 0;
type ComponentParameters = object | null | undefined;
let manager: DotNet.DotNetObject | undefined;
let currentRendererId: number | undefined;
let jsComponentParametersByIdentifier: JSComponentParametersByIdentifier;
let hasInitializedJsComponents = false;
// These are the public APIs at Blazor.rootComponents.*
export const RootComponentsFunctions = {
async add(toElement: Element, componentIdentifier: string, initialParameters: ComponentParameters): Promise<DynamicRootComponent> {
if (!initialParameters) {
throw new Error('initialParameters must be an object, even if empty.');
}
// Track the container so we can use it when the component gets attached to the document via a selector
const containerIdentifier = pendingRootComponentContainerNamePrefix + (++nextPendingDynamicRootComponentIdentifier).toString();
pendingRootComponentContainers.set(containerIdentifier, toElement);
// Instruct .NET to add and render the new root component
const componentId = await getRequiredManager().invokeMethodAsync<number>('AddRootComponent', componentIdentifier, containerIdentifier);
const component = new DynamicRootComponent(componentId, jsComponentParametersByIdentifier[componentIdentifier]);
await component.setParameters(initialParameters);
return component;
},
};
export function getAndRemovePendingRootComponentContainer(containerIdentifier: string): Element | undefined {
const container = pendingRootComponentContainers.get(containerIdentifier);
if (container) {
pendingRootComponentContainers.delete(containerIdentifier);View on GitHub (pinned to 3600ca084e)