Skip to content

Mermaid diagrams are missing from the published docs site (dropped at build time since #6021) #6062

Description

@andygrove

Describe the bug

None of the three mermaid diagrams on the published site render. They are not blank or broken images — they are absent from the HTML entirely.

This is a different cause from #6020, which was the client-side renderer being blocked by the ASF Content-Security-Policy. #6021 fixed that by switching to build-time SVG (mermaid_output_format = 'svg'), and in doing so replaced one silent failure with another.

Steps to reproduce

Fetch the deployed pages from the asf-site branch and look for any diagram:

$ gh api "repos/apache/datafusion-comet/contents/contributor-guide/memory_management.html?ref=asf-site" \
    --jq .content | base64 -d | grep -c 'svg\|mermaid\|<object'
0
$ gh api "repos/apache/datafusion-comet/contents/contributor-guide/ci.html?ref=asf-site" \
    --jq .content | base64 -d | grep -c 'svg\|mermaid\|<object'
0
$ gh api "repos/apache/datafusion-comet/git/trees/asf-site?recursive=1" \
    --jq '[.tree[].path | select(test("mermaid"))] | length'
0

On contributor-guide/memory_management.html the text runs straight from
…who ends up charged for the bytes:</p> into the next <section> heading.

The hand-authored SVGs (shim_pattern.svg, query_context_journey.svg, error_pipeline_overview.svg) are all present, so this is specific to the mermaid pipeline.

Expected behavior

The two diagrams in docs/source/contributor-guide/memory_management.md and the one in docs/source/contributor-guide/ci.md render on the published pages.

Additional context

What is happening. sphinxcontrib-mermaid downgrades a render failure to a Sphinx warning and drops the node. The build stays green, the deploy runs, and the pages publish with a diagram-shaped hole. docs/README.md and the comment on the Install mermaid-cli step in .github/workflows/docs.yaml both already warn that this is the failure mode; nothing enforces it.

The publish commit for #6021 (b9ea47c16) shows it exactly: it removed the <pre class="mermaid"> blocks and the jsdelivr script import from both pages and added nothing in their place — no <object>, and no _images/mermaid-*.svg anywhere in the tree.

So mmdc is not producing output in the docs job, even though the job is green and Install mermaid-cli succeeds (21s in the run for d1bf687eb).

Why it was not caught. #6021 was verified locally on macOS, where it produced 2 and 1 <object> embeds on those two pages. The docs job only runs on push to main (ci.yml, docs is push-tier by POLICY), so no docs build ran on the pull request, and once on main the failure is silent by construction.

Likely cause. mmdc drives headless Chrome through puppeteer. Ubuntu restricts unprivileged user namespaces by AppArmor policy from 23.10 onwards, so Chrome's setuid sandbox cannot start on an ubuntu-24.04 runner and mmdc exits non-zero — the canonical "renders locally, dies in CI" shape for mermaid-cli. The alternative is puppeteer's Chrome not being where mmdc looks after a global install. Either way sphinxcontrib-mermaid swallows it, and the job log is the only place the difference shows.

Proposed fix

  1. Pass mmdc a puppeteer config with --no-sandbox (the CI container is already the isolation boundary).
  2. Make the failure loud: render every ```mermaid fence in preflight so it fails on the pull request, and assert after the build that every fence produced a non-empty SVG that some page references, before the publish step runs.

Component(s)

Documentation

Activity

  1. added
    bugSomething isn't working
    documentationImprovements or additions to documentation
    on Sep 20, 2026
  2. andygrove commented on Sep 20, 2026

    @andygrove
    MemberAuthor

    Refining the "likely cause" above, because a local reproduction turned up a second candidate that is at least as likely, and a third layer of swallowing.

    @mermaid-js/mermaid-cli declares puppeteer as a peer dependency and ships puppeteer-core, so the browser mmdc drives comes from puppeteer's postinstall. That script is:

    try {
      const {downloadBrowsers} = await importInstaller();
      await downloadBrowsers();
    } catch (error) {
      console.warn('Browser download failed', error);
    }

    It catches its own failure and exits 0. So a flaky or blocked browser fetch during npm install -g @mermaid-js/mermaid-cli@11.17.0 leaves a green install step with no browser, and mmdc then dies at launch:

    Error: Could not find chrome-headless-shell (ver. 153.0.8010.36). This can occur if either
     1. you did not perform an installation before running the script ...
    

    which sphinxcontrib-mermaid turns into a warning and a dropped diagram. Three layers, each one silent.

    That is the exact error the reproduction produced. It does not prove it is what happened on the runner — the browser fetch is blocked in my environment, so I cannot separate it from the AppArmor sandbox theory, and the job log for the docs run is not reachable from here. But it does mean there are two plausible causes rather than one, and both are cheap to close out:

    • an explicit puppeteer browsers install chrome-headless-shell after the npm install, where a failure is allowed to fail the job, removes the silent-no-browser case
    • the --no-sandbox puppeteer config removes the AppArmor case

    Whichever one it was, the render check reports the actual mmdc stderr, so the next docs run says so outright instead of publishing a hole.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdocumentationImprovements or additions to documentationrequires-triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions