iOfficeAI/OfficeCLI · error · InvalidOperationException
headless browser produced no output.
Error message
headless browser produced no output.
What it means
The chrome-family renderer writes an HTML file and asks HtmlScreenshot.DumpDom to load it in a headless browser and return the rendered DOM. DumpDom returned null — the browser produced no output at all. This is the earliest failure point in the two-pass chrome path: the DOM dump (used to read the diagram's viewBox and the MMDREADY/MMDSYNTAX/MMDERR title) never came back.
Source
Thrown at src/officecli/Core/Diagram/MermaidImageRenderer.cs:364
// ----- chrome-family browser (mermaid.js in a page → sized screenshot) --------------
/// <summary>Two chrome passes: dump the DOM to read the diagram's viewBox, then
/// screenshot at exactly that size (HiDPI). PNG bakes in the browser's rendering
/// so mermaid's foreignObject labels — invisible to Office as SVG — appear.</summary>
private static string RenderViaChrome(string mermaid, string? background)
{
// A styled source (theme/layout/look frontmatter) is rendered by the ESM
// build (the UMD global does not render frontmatter, and elk is ESM-only);
// a plain source keeps the offline-cached UMD path unchanged.
var html = SourceNeedsEsm(mermaid)
? BuildHtmlEsm(mermaid, SourceNeedsElk(mermaid), SafeBackground(background))
: BuildHtml(mermaid, ResolveMermaidJsRef(), SafeBackground(background));
var htmlPath = Path.Combine(Path.GetTempPath(), $"ocli_mmd_{Guid.NewGuid():N}.html");
File.WriteAllText(htmlPath, html);
try
{
var dom = HtmlScreenshot.DumpDom(htmlPath)
?? throw new InvalidOperationException("headless browser produced no output.");
// The <title> is the AUTHORITATIVE outcome — not the presence of an <svg>.
// On a syntax error mermaid.parse() rejects (we capture the message) but
// STILL injects its red "Syntax error" bomb graphic into the DOM anyway
// (suppressErrorRendering doesn't stop it). So a viewBox is present even on
// failure; keying off the svg would screenshot the bomb and "succeed".
// Trust the title: MMDREADY = real render, MMDSYNTAX = bad input, else infra.
if (dom.Contains("<title>MMDSYNTAX</title>", StringComparison.Ordinal))
throw new MermaidSyntaxException(
"mermaid syntax error: " + ExtractMermaidMessage(dom)
+ "\n(fix the mermaid source, or use render=native for the built-in subset).");
if (!dom.Contains("<title>MMDREADY</title>", StringComparison.Ordinal))
throw new InvalidOperationException(
dom.Contains("<title>MMDERR</title>", StringComparison.Ordinal)
? "mermaid failed to render: " + ExtractMermaidMessage(dom)
: "mermaid produced no diagram (mermaid.js failed to load or the render timed out).");
var (w, h) = ParseSvgSize(dom);View on GitHub (pinned to 1ced45e900)
Solutions
- Verify headless chrome launches: run `chrome --headless --dump-dom file:///tmp/x.html` directly.
- If running as root/in a container, ensure the headless launch flags include --no-sandbox (or run as a non-root user).
- Confirm chrome is discoverable by the tool's resolver (set the chrome path env var the resolver honors).
- Install missing chrome runtime libraries; fall back to render=native if chrome cannot be made to run.
Example fix
// before
var dom = HtmlScreenshot.DumpDom(htmlPath)
?? throw new InvalidOperationException("headless browser produced no output.");
// after — distinguish launch failure from empty DOM for a clearer error
var dom = HtmlScreenshot.DumpDom(htmlPath);
if (dom is null)
throw new InvalidOperationException(
HtmlScreenshot.ChromeAvailable()
? "headless browser produced no output (chrome launched but returned no DOM)."
: "headless chrome not found or failed to launch; install chrome or use render=native."); Defensive patterns
Strategy: validation
Validate before calling
// Confirm chrome is launchable before the DOM-dump path
if (!HtmlScreenshot.ChromeAvailable())
throw new InvalidOperationException("headless chrome not found; install it or use render=native."); Try / catch
try
{
dom = HtmlScreenshot.DumpDom(htmlPath)
?? throw new InvalidOperationException("headless browser produced no output.");
}
catch (InvalidOperationException ex) when (ex.Message.Contains("no output", StringComparison.Ordinal))
{
png = MermaidImageRenderer.RenderNative(mermaid, bg);
} Prevention
- Run chrome with --no-sandbox in root/container contexts.
- Keep chrome and its runtime libs installed.
- Validate the html temp path is writable.
When it happens
Trigger: HtmlScreenshot.DumpDom returns null when the headless browser failed to launch or crashed before emitting any DOM — missing chrome binary, chrome killed on launch (sandbox/permissions), a timeout inside DumpDom itself, or the html path being unreadable.
Common situations: Running headless chrome as root without --no-sandbox; chrome not installed or not on the resolver path; a locked-down CI container that blocks process spawning; an OS update removed a chrome dependency library.
Related errors
- headless screenshot failed.
- mmdc failed (exit {p.ExitCode}). {msg}
- mermaid failed to render: {ExtractMermaidMessage(dom)}
- mermaid produced no diagram (mermaid.js failed to load or th
- failed to start mmdc.
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/1a809731bef56dd6.
Report an issue: GitHub.