Skip to content

Mermaid PNG export fails for SVGs with xlink:href because generated SVG is not XML-valid #541

Description

@SebastianBodza

Bug Description

Some Mermaid diagrams rendered through Streamdown cannot be exported as PNG. The diagram renders visually in the browser, but clicking the PNG download option does nothing / fails silently.

The issue happens when Mermaid returns SVG that contains attributes such as xlink:href without declaring the required xmlns:xlink namespace on the root <svg> element.

Streamdown’s Mermaid PNG export path converts the returned SVG into an image and then draws it to a canvas. Browsers require the SVG to be valid XML for this image-loading step. If the SVG contains xlink:href but no xmlns:xlink, the image load fails and PNG export cannot complete.

This is similar to the existing issue class where Mermaid SVG may contain HTML-style <br> tags, which are also invalid in XML/SVG serialization unless normalized to <br />. #516

Affected packages

Observed with:

streamdown: 2.5.0
@streamdown/mermaid: 1.0.2
mermaid: 11.x
browser: Chromium / Edge

Minimal Mermaid diagram that reproduces it

```mermaid
C4Context
    title Generic system context
    Person(user, "User", "Uses digital services")
    System(application, "Application", "Web and mobile service platform")
    System_Ext(systemA, "External System A", "Provides account data")
    System_Ext(systemB, "External System B", "Provides customer data")
    Rel(user, application, "Uses")
    Rel(application, systemA, "Reads data from")
    Rel(application, systemB, "Reads data from")
```

Root cause

Mermaid can emit SVG like this:

<svg id="..." xmlns="http://www.w3.org/2000/svg" ...>
  ...
  <image xlink:href="..." />
  ...
</svg>

But the SVG root is missing:

xmlns:xlink="http://www.w3.org/1999/xlink"

Because of that, XML/SVG parsing fails with an error equivalent to:

The prefix "xlink" for attribute "xlink:href" associated with an element type "image" is not bound.

Streamdown currently passes this SVG through unchanged into its PNG export conversion. The browser image load fails, so the canvas conversion never succeeds.

Expected behavior

Streamdown should normalize Mermaid SVG before display/export, especially before PNG conversion.

If SVG contains xlink: and no xmlns:xlink, add:

xmlns:xlink="http://www.w3.org/1999/xlink"

Steps to Reproduce

Minimal reproduction

import { mermaid } from "@streamdown/mermaid";
import { Streamdown } from "streamdown";

const markdown = `
\`\`\`mermaid
C4Context
    title Generic system context
    Person(user, "User", "Uses digital services")
    System(application, "Application", "Web and mobile service platform")
    System_Ext(systemA, "External System A", "Provides account data")
    System_Ext(systemB, "External System B", "Provides customer data")
    Rel(user, application, "Uses")
    Rel(application, systemA, "Reads data from")
    Rel(application, systemB, "Reads data from")
\`\`\`
`;

export default function App() {
  return <Streamdown plugins={{ mermaid }}>{markdown}</Streamdown>;
}

Steps:

  1. Render the markdown above with Streamdown and @streamdown/mermaid.
  2. Open the Mermaid block download menu.
  3. Click PNG.

Expected Behavior

Expected:

  • PNG file is downloaded.

Actual Behavior

Actual:

  • PNG export fails / no PNG is downloaded.

Code Sample

Streamdown Version

2.5.0

React Version

19.2.5

Node.js Version

24.13.0

Browser(s)

Chrome

Operating System

Windows

Additional Context

@streamdown/mermaid version 1.0.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions