iOfficeAI/OfficeCLI · error · InvalidOperationException
failed to start mmdc.
Error message
failed to start mmdc.
What it means
Thrown by RenderViaMmdc (MermaidImageRenderer.cs:319) when Process.Start returns null for the located mmdc executable. mmdc is located via the OFFICECLI_MMDC env var (explicit path) or the PATH. If Process.Start cannot launch the resolved path (e.g. it is not a real executable, lacks execute permission, or the platform returns null), this fires. Note RenderToPngFile catches this and cascades to the chrome-family backend, so the user only sees it when both backends fail; the final thrown error is whichever backend's failure was recorded first.
Source
Thrown at src/officecli/Core/Diagram/MermaidImageRenderer.cs:319
RedirectStandardOutput = true,
// CONSISTENCY(child-stream-encoding): see BlankDocCreator.
StandardOutputEncoding = System.Text.Encoding.UTF8,
StandardErrorEncoding = System.Text.Encoding.UTF8,
UseShellExecute = false,
CreateNoWindow = true,
};
psi.ArgumentList.Add("-i"); psi.ArgumentList.Add(inPath);
psi.ArgumentList.Add("-o"); psi.ArgumentList.Add(outPath);
psi.ArgumentList.Add("-b"); psi.ArgumentList.Add(SafeBackground(background));
psi.ArgumentList.Add("-s"); psi.ArgumentList.Add("2"); // HiDPI for crisp raster
var pcfg = Environment.GetEnvironmentVariable("OFFICECLI_MMDC_PUPPETEER");
if (!string.IsNullOrWhiteSpace(pcfg) && File.Exists(pcfg))
{
psi.ArgumentList.Add("-p"); psi.ArgumentList.Add(pcfg);
}
using var p = Process.Start(psi)
?? throw new InvalidOperationException("failed to start mmdc.");
// Async-drain both streams: the serial stderr-then-stdout reads
// interlocked when mmdc filled the stdout pipe first (bounded by
// the 120s kill below, but a wasted two minutes per diagram).
var errTask = p.StandardError.ReadToEndAsync();
var outTask = p.StandardOutput.ReadToEndAsync();
if (!p.WaitForExit(120_000))
{
try { p.Kill(true); } catch { /* best effort */ }
throw new InvalidOperationException("mmdc timed out after 120s.");
}
if (p.ExitCode != 0 || !File.Exists(outPath))
{
var msg = $"{errTask.Result}{outTask.Result}".Trim();
// A parse/unknown-type failure is bad input, not a broken mmdc; class
// it as syntax so the Add path surfaces it (and does not fall back).
if (LooksLikeSyntaxError(msg))
throw new MermaidSyntaxException(
$"mermaid syntax error: {msg} "View on GitHub (pinned to 1ced45e900)
Solutions
- Install mermaid-cli globally (npm install -g @mermaid-js/mermaid-cli) and verify 'mmdc -V' runs.
- Set OFFICECLI_MMDC to the absolute path of the actual executable (e.g. /usr/bin/mmdc or the .cmd on Windows), not the package folder.
- Ensure the resolved path has execute permission (chmod +x on Linux/macOS).
- If mmdc cannot be fixed, ensure a chrome-family browser (Chrome/Chromium/Edge) is installed so the chrome fallback backend succeeds.
Example fix
// before export OFFICECLI_MMDC=/usr/lib/node_modules/@mermaid-js/mermaid-cli // after export OFFICECLI_MMDC=/usr/lib/node_modules/@mermaid-js/mermaid-cli/src/cli.js # or simply rely on a working PATH install: npm install -g @mermaid-js/mermaid-cli unset OFFICECLI_MMDC
Defensive patterns
Strategy: validation
Validate before calling
static void EnsureMmdcAvailable()
{
var exe = Environment.GetEnvironmentVariable("OFFICECLI_MMDC");
if (!string.IsNullOrWhiteSpace(exe) && !File.Exists(exe))
throw new InvalidOperationException($"OFFICECLI_MMDC points to a missing file: {exe}");
if (string.IsNullOrWhiteSpace(exe) && HtmlScreenshot.Which("mmdc") == null)
throw new InvalidOperationException("mmdc not found on PATH; install mermaid-cli or set OFFICECLI_MMDC");
}
// call before RenderToPngFile, or gate on MermaidImageRenderer.IsAvailable() Type guard
// no static type guard; use the availability check: static bool CanRenderViaMmdcOrChrome() => MermaidImageRenderer.IsAvailable();
Try / catch
try { var png = MermaidImageRenderer.RenderToPngFile(mermaid, bg); }
catch (InvalidOperationException ex) when (ex.Message.Contains("mmdc") || ex.Message.Contains("mermaid-cli"))
{
// no image backend works — fall back to the native synthesizer
var graph = DiagramCompiler.Compile(mermaid);
} Prevention
- Install mermaid-cli (npm install -g @mermaid-js/mermaid-cli) and verify 'mmdc -V'.
- Point OFFICECLI_MMDC at the actual executable entry point, not the package directory.
- Ensure execute permission on the resolved path (chmod +x).
- Keep a chrome-family browser installed so the chrome fallback backend can cover mmdc outages.
When it happens
Trigger: OFFICECLI_MMDC points to a file that is not executable or is a script without a shebang/extension the OS can launch; mmdc was found on PATH but is a broken symlink or a non-executable shim; Process.Start returns null on the current platform for the resolved path.
Common situations: Pointing OFFICECLI_MMDC at the npm package directory instead of the bin/mmdc entry; a PATH entry that resolves to a .js source file rather than the installed CLI wrapper; permission bits missing on Linux/macOS after a manual copy.
Related errors
- mmdc timed out after 120s.
- mmdc failed (exit {p.ExitCode}). {msg}
- diagram type '{kind}' is not supported yet (currently: flowc
- diagram has no nodes — the mermaid source has no node/edge s
- unknown diagram theme '{theme}'. Valid: {string.Join(", ", T
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/23e392ba3ae0aeff.
Report an issue: GitHub.