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

  1. Ensure consistent @key usage on components so Blazor pairs the right descriptors.
  2. Verify the route and parameters match between the streamed update and the existing DOM.
  3. Match framework versions so locationHash/formattedComponentKey computation agrees.
  4. 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

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


AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06). Data as JSON: /api/errors/bc6b0d6f1699d76a. Report an issue: GitHub.