{"record":{"id":"23e392ba3ae0aeff","repo":"iOfficeAI/OfficeCLI","slug":"failed-to-start-mmdc","errorCode":null,"errorMessage":"failed to start mmdc.","messagePattern":"failed to start mmdc\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/Diagram/MermaidImageRenderer.cs","lineNumber":319,"sourceCode":"                RedirectStandardOutput = true,\n                // CONSISTENCY(child-stream-encoding): see BlankDocCreator.\n                StandardOutputEncoding = System.Text.Encoding.UTF8,\n                StandardErrorEncoding = System.Text.Encoding.UTF8,\n                UseShellExecute = false,\n                CreateNoWindow = true,\n            };\n            psi.ArgumentList.Add(\"-i\"); psi.ArgumentList.Add(inPath);\n            psi.ArgumentList.Add(\"-o\"); psi.ArgumentList.Add(outPath);\n            psi.ArgumentList.Add(\"-b\"); psi.ArgumentList.Add(SafeBackground(background));\n            psi.ArgumentList.Add(\"-s\"); psi.ArgumentList.Add(\"2\"); // HiDPI for crisp raster\n            var pcfg = Environment.GetEnvironmentVariable(\"OFFICECLI_MMDC_PUPPETEER\");\n            if (!string.IsNullOrWhiteSpace(pcfg) && File.Exists(pcfg))\n            {\n                psi.ArgumentList.Add(\"-p\"); psi.ArgumentList.Add(pcfg);\n            }\n\n            using var p = Process.Start(psi)\n                ?? throw new InvalidOperationException(\"failed to start mmdc.\");\n            // Async-drain both streams: the serial stderr-then-stdout reads\n            // interlocked when mmdc filled the stdout pipe first (bounded by\n            // the 120s kill below, but a wasted two minutes per diagram).\n            var errTask = p.StandardError.ReadToEndAsync();\n            var outTask = p.StandardOutput.ReadToEndAsync();\n            if (!p.WaitForExit(120_000))\n            {\n                try { p.Kill(true); } catch { /* best effort */ }\n                throw new InvalidOperationException(\"mmdc timed out after 120s.\");\n            }\n            if (p.ExitCode != 0 || !File.Exists(outPath))\n            {\n                var msg = $\"{errTask.Result}{outTask.Result}\".Trim();\n                // A parse/unknown-type failure is bad input, not a broken mmdc; class\n                // it as syntax so the Add path surfaces it (and does not fall back).\n                if (LooksLikeSyntaxError(msg))\n                    throw new MermaidSyntaxException(\n                        $\"mermaid syntax error: {msg} \"","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/Diagram/MermaidImageRenderer.cs#L301-L337","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nexport OFFICECLI_MMDC=/usr/lib/node_modules/@mermaid-js/mermaid-cli\n// after\nexport OFFICECLI_MMDC=/usr/lib/node_modules/@mermaid-js/mermaid-cli/src/cli.js\n# or simply rely on a working PATH install:\nnpm install -g @mermaid-js/mermaid-cli\nunset OFFICECLI_MMDC","handlingStrategy":"validation","validationCode":"static void EnsureMmdcAvailable()\n{\n    var exe = Environment.GetEnvironmentVariable(\"OFFICECLI_MMDC\");\n    if (!string.IsNullOrWhiteSpace(exe) && !File.Exists(exe))\n        throw new InvalidOperationException($\"OFFICECLI_MMDC points to a missing file: {exe}\");\n    if (string.IsNullOrWhiteSpace(exe) && HtmlScreenshot.Which(\"mmdc\") == null)\n        throw new InvalidOperationException(\"mmdc not found on PATH; install mermaid-cli or set OFFICECLI_MMDC\");\n}\n\n// call before RenderToPngFile, or gate on MermaidImageRenderer.IsAvailable()","typeGuard":"// no static type guard; use the availability check:\nstatic bool CanRenderViaMmdcOrChrome() => MermaidImageRenderer.IsAvailable();","tryCatchPattern":"try { var png = MermaidImageRenderer.RenderToPngFile(mermaid, bg); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"mmdc\") || ex.Message.Contains(\"mermaid-cli\"))\n{\n    // no image backend works — fall back to the native synthesizer\n    var graph = DiagramCompiler.Compile(mermaid);\n}","preventionTips":["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."],"tags":["diagram","mermaid","mmdc","infrastructure","process"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}