dotnet/aspnetcore · error
Cannot merge mismatching component descriptors: ${JSON.strin
Error message
Cannot merge mismatching component descriptors:
${JSON.stringify(target)}
and
${JSON.stringify(source)} What it means
Thrown by mergeDescriptors (ComponentDescriptorDiscovery.ts:351) when canMergeDescriptors returns false. Two descriptors can merge only if they share the same 'type' AND their 'key' (locationHash + formattedComponentKey) match. This guards against merging descriptors that describe different logical components (e.g. different routes or component keys) during streaming SSR reconciliation.
Source
Thrown at src/Components/Web.JS/src/Services/ComponentDescriptorDiscovery.ts:351
} as unknown as ComponentMarker;
}
function doKeysMatch(a: MarkerKey | undefined, b: MarkerKey | undefined) {
if (!a || !b) {
// Unspecified keys are never considered to be matching
return false;
}
return a.locationHash === b.locationHash && a.formattedComponentKey === b.formattedComponentKey;
}
export function canMergeDescriptors(target: ComponentDescriptor, source: ComponentDescriptor): boolean {
return target.type === source.type && doKeysMatch(target.key, source.key);
}
export function mergeDescriptors(target: ComponentDescriptor, source: ComponentDescriptor) {
if (!canMergeDescriptors(target, source)) {
throw new Error(`Cannot merge mismatching component descriptors:\n${JSON.stringify(target)}\nand\n${JSON.stringify(source)}`);
}
target.uniqueId = source.uniqueId;
if (target.type === 'webassembly' || target.type === 'auto') {
const sourceWebAssemblyData = source as WebAssemblyMarkerData;
target.parameterDefinitions = sourceWebAssemblyData.parameterDefinitions;
target.parameterValues = sourceWebAssemblyData.parameterValues;
}
if (target.type === 'server' || target.type === 'auto') {
const sourceServerData = source as ServerMarkerData;
target.sequence = sourceServerData.sequence;
target.descriptor = sourceServerData.descriptor;
}
}
export type ComponentDescriptor = ServerComponentDescriptor | WebAssemblyComponentDescriptor | AutoComponentDescriptor;View on GitHub (pinned to 294cab2f9b)
Solutions
- Ensure consistent @key usage on components so Blazor pairs the right descriptors.
- Verify the route and parameters match between the streamed update and the existing DOM.
- Match framework versions so locationHash/formattedComponentKey computation agrees.
- Reproduce with enhanced nav disabled to confirm the issue is in descriptor merging, then fix the @key/route source.
Example fix
<!-- before: list items without stable keys -->
@foreach (var item in Items) { <MyItem Item="item" /> }
<!-- after: stable keys prevent descriptor mis-pairing -->
@foreach (var item in Items) { <MyItem Item="item" @key="item.Id" /> } Defensive patterns
Strategy: validation
Validate before calling
import { canMergeDescriptors } from './ComponentDescriptorDiscovery';
function safeMerge(target, source) {
if (!canMergeDescriptors(target, source)) {
throw new Error('Refusing to merge mismatched descriptors — check @key/route parity');
}
mergeDescriptors(target, source);
} Type guard
function keysMatch(a, b): boolean {
return !!a && !!b && a.locationHash === b.locationHash
&& a.formattedComponentKey === b.formattedComponentKey;
} Try / catch
try {
mergeDescriptors(target, source);
} catch (e) {
if (/Cannot merge mismatching component descriptors/.test((e as Error).message)) {
// log and skip; reconcile via full re-render instead of merging
} else { throw e; }
} Prevention
- Use stable @key on list items and routable components.
- Keep route parameters consistent between streamed updates and DOM.
- Pin framework versions so locationHash/formatting agree.
When it happens
Trigger: Calling mergeDescriptors on two descriptors whose type differs, or whose key.locationHash / key.formattedComponentKey differ (or one/both keys are undefined). Reached during enhanced-navigation DOM syncing when an incoming streamed update targets a different component than the one already in the DOM.
Common situations: Navigating between pages that share DOM structure but different component keys/route parameters; @key mismatches causing Blazor to pair wrong elements; prerendered content from a different route lingering in the DOM; version mismatch in key hashing.
Related errors
- Could not find an end component comment for '${start}'.
- Found malformed component comment at ${candidateStart.textCo
- Invalid component type '${type}'.
- Root components cannot be marked as interactive. The <html>
- Invalid end of component comment: '${json}'
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/bc6b0d6f1699d76a.
Report an issue: GitHub.