dotnet/aspnetcore · error · Error

Found malformed component comment at

Error message

Found malformed component comment at ${candidateStart.textContent}

What it means

Thrown during component-marker discovery when parsing a Blazor component comment (server/webassembly/auto) raises any exception inside the try block. The catch wraps the underlying error with the comment's textContent for diagnostics. This is a generic 'the prerendered component marker HTML is malformed' signal; the original parse/validation error is masked by this wrapper.

Solutions

  1. Inspect the raw HTML served to the browser and confirm the <!--Blazor:{...}--> comments are intact and well-formed JSON.
  2. Disable HTML comment stripping in any minifier, CDN, or output cache.
  3. Align the server (prerendering) and client Blazor package versions.
  4. Reproduce by viewing page source and locate the comment whose content is shown in the message, then fix its payload.
  5. If a custom serializer is involved, ensure it emits the exact marker schema.
Defensive patterns

Strategy: validation

Validate before calling

// Validate served HTML before Blazor reads markers.
function assertCommentsIntact(html: string) {
  const open = (html.match(/<!--Blazor:/g) || []).length;
  const close = (html.match(/-->/g) || []).length;
  if (open === 0) throw new Error('No Blazor component comments found in prerendered HTML.');
}

Prevention

When it happens

Trigger: The HTML contains a <!--Blazor:...--> comment whose JSON payload is invalid or missing required fields; a custom HTML pipeline (e.g. an aggressive minifier) rewrote or stripped part of the marker; partial HTML streaming cut a comment in half.

Common situations: Output caching/compression that mangles comment payloads; a CDN or proxy that strips HTML comments; hand-edited _Host that broke the marker; version mismatch between prerendering server and client runtime producing different marker schemas.

Understand the failure class

Related errors


AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11). Data as JSON: /api/errors/3e3fc6f62aee7131. Report an issue: GitHub.

Appendix: source

Thrown at src/Components/Web.JS/src/Services/ComponentDescriptorDiscovery.ts:161

        // Regardless of whether this comment matches the type we're looking for, we still need to move the iterator
        // on to its end position since we don't want to recurse into unrelated prerendered components, nor do we want to get confused
        // by the end marker.
        const candidateEnd = getComponentEndComment(componentComment, candidateStart as Comment, commentNodeIterator);

        if (type !== componentComment.type) {
          return undefined;
        }

        switch (componentComment.type) {
          case 'webassembly':
            return createWebAssemblyComponentComment(componentComment, candidateStart as Comment, candidateEnd);
          case 'server':
            return createServerComponentComment(componentComment, candidateStart as Comment, candidateEnd);
          case 'auto':
            return createAutoComponentComment(componentComment, candidateStart as Comment, candidateEnd);
        }
      } catch (error) {
        throw new Error(`Found malformed component comment at ${candidateStart.textContent}`);
      }
    } else {
      return;
    }
  }
}

function parseCommentPayload(json: string): ServerComponentMarker | WebAssemblyComponentMarker | AutoComponentMarker {
  const payload = JSON.parse(json);
  const { type } = payload;
  if (type !== 'server' && type !== 'webassembly' && type !== 'auto') {
    throw new Error(`Invalid component type '${type}'.`);
  }

  return payload;
}

function assertNotDirectlyOnDocument(marker: Node) {

View on GitHub (pinned to 3600ca084e)