{"record":{"id":"3154f0903bd354ee","repo":"iOfficeAI/OfficeCLI","slug":"headless-screenshot-failed","errorCode":null,"errorMessage":"headless screenshot failed.","messagePattern":"headless screenshot failed\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/Diagram/MermaidImageRenderer.cs","lineNumber":389,"sourceCode":"            // Trust the title: MMDREADY = real render, MMDSYNTAX = bad input, else infra.\n            if (dom.Contains(\"<title>MMDSYNTAX</title>\", StringComparison.Ordinal))\n                throw new MermaidSyntaxException(\n                    \"mermaid syntax error: \" + ExtractMermaidMessage(dom)\n                    + \"\\n(fix the mermaid source, or use render=native for the built-in subset).\");\n            if (!dom.Contains(\"<title>MMDREADY</title>\", StringComparison.Ordinal))\n                throw new InvalidOperationException(\n                    dom.Contains(\"<title>MMDERR</title>\", StringComparison.Ordinal)\n                    ? \"mermaid failed to render: \" + ExtractMermaidMessage(dom)\n                    : \"mermaid produced no diagram (mermaid.js failed to load or the render timed out).\");\n\n            var (w, h) = ParseSvgSize(dom);\n            if (w <= 0 || h <= 0)\n                throw new InvalidOperationException(\"mermaid rendered but produced no measurable svg viewBox.\");\n\n            var pngPath = Path.ChangeExtension(htmlPath, \".png\");\n            if (!HtmlScreenshot.CaptureChromeSized(htmlPath, pngPath,\n                    (int)Math.Ceiling(w) + 2, (int)Math.Ceiling(h) + 2))\n                throw new InvalidOperationException(\"headless screenshot failed.\");\n            return pngPath;\n        }\n        finally { try { File.Delete(htmlPath); } catch { /* best effort */ } }\n    }\n\n    /// <summary>Cache → one-time download → live CDN. Returns a URL usable as a\n    /// &lt;script src&gt; (a <c>file://</c> for a cached/downloaded copy, else the CDN).</summary>\n    private static string ResolveMermaidJsRef()\n    {\n        try\n        {\n            if (File.Exists(CachedJsPath) && new FileInfo(CachedJsPath).Length > 500_000)\n                return new Uri(CachedJsPath).AbsoluteUri;\n\n            Directory.CreateDirectory(CacheDir);\n            foreach (var url in new[] { MirrorUrl, CdnUrl }) // mirror first, CDN fallback\n            {\n                try","sourceCodeStart":371,"sourceCodeEnd":407,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/Diagram/MermaidImageRenderer.cs#L371-L407","documentation":"The two-pass chrome path succeeded in pass one (DOM dump, MMDREADY, a valid viewBox), but the second pass — HtmlScreenshot.CaptureChromeSized writing the PNG at ceil(w)+2 x ceil(h)+2 — returned false. The screenshot capture itself failed; the diagram was valid but the rasterization step broke.","triggerScenarios":"CaptureChromeSized returns false when the headless screenshot call fails: chrome crashed mid-capture, the output path wasn't writable, the viewport size was rejected, or a chrome timeout during the screenshot pass.","commonSituations":"Temp directory not writable / out of disk; chrome instability under rapid repeated launches (flaky in CI); extremely large computed viewport (huge diagram) that chrome refuses; antivirus/SELinux blocking the PNG write.","solutions":["Check the temp path is writable and has free space.","Retry once — chrome screenshot failures are often transient.","For very large diagrams, scale down or use render=native.","Ensure chrome isn't being killed by a resource limit (ulimit/cgroup memory) during capture."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Confirm the temp path is writable and disk isn't full before the screenshot pass\nvar tmp = Path.GetTempPath();\nif (!HasFreeSpace(tmp)) throw new InvalidOperationException(\"temp volume full; cannot write screenshot.\");","typeGuard":null,"tryCatchPattern":"for (int attempt = 0; ; attempt++)\n{\n    try { return HtmlScreenshot.CaptureChromeSized(htmlPath, pngPath, w, h)\n        ? pngPath : throw new InvalidOperationException(\"headless screenshot failed.\"); }\n    catch (InvalidOperationException ex) when (ex.Message.Contains(\"screenshot failed\", StringComparison.Ordinal) && attempt < 1)\n    { /* chrome flake — retry once */ }\n}","preventionTips":["Keep temp volume with free space and writable.","Retry once on screenshot failures (often transient chrome flake).","Avoid extremely large viewports that chrome may reject."],"tags":["mermaid","chrome","screenshot","infrastructure","io"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}