iOfficeAI/OfficeCLI · error · ArgumentException

unknown diagram layout '{layout}'. Valid: {string.Join(", ",

Error message

unknown diagram layout '{layout}'. Valid: {string.Join(", ", Layouts)}.

What it means

Thrown by MermaidImageRenderer.ComposeSource (MermaidImageRenderer.cs:134) when a non-null layout value is not in the accepted Layouts set {dagre, elk} (case-insensitive). dagre is mermaid's default layered layout; elk requires the ESM elk loader registered at render time. Unknown layout values are rejected before frontmatter injection.

Source

Thrown at src/officecli/Core/Diagram/MermaidImageRenderer.cs:134

    /// <c>--- config: … ---</c> frontmatter block, so they render AND round-trip
    /// (the composed source is what gets stamped into alt-text). Returns the
    /// source unchanged when no option is set. Rejects unknown values with a
    /// message listing the valid ones. When the source already carries its own
    /// frontmatter or an <c>%%{init}%%</c> directive, the source wins and the
    /// options are ignored (caller may warn) — merging into an existing block is
    /// out of scope and would risk producing a malformed document.
    /// </summary>
    public static string ComposeSource(string mermaid, string? theme, string? layout, string? look)
    {
        theme = string.IsNullOrWhiteSpace(theme) ? null : theme.Trim();
        layout = string.IsNullOrWhiteSpace(layout) ? null : layout.Trim();
        look = string.IsNullOrWhiteSpace(look) ? null : look.Trim();
        if (theme == null && layout == null && look == null) return mermaid;

        if (theme != null && !Themes.Contains(theme))
            throw new ArgumentException($"unknown diagram theme '{theme}'. Valid: {string.Join(", ", Themes)}.");
        if (layout != null && !Layouts.Contains(layout))
            throw new ArgumentException($"unknown diagram layout '{layout}'. Valid: {string.Join(", ", Layouts)}.");
        if (look != null && !Looks.Contains(look))
            throw new ArgumentException($"unknown diagram look '{look}'. Valid: classic, handDrawn.");

        var lead = mermaid.TrimStart();
        if (lead.StartsWith("---", StringComparison.Ordinal) || lead.StartsWith("%%{", StringComparison.Ordinal))
            return mermaid; // source already declares config — do not double-inject

        var sb = new StringBuilder("---\nconfig:\n");
        if (theme != null) sb.Append("  theme: ").Append(theme.ToLowerInvariant()).Append('\n');
        if (layout != null) sb.Append("  layout: ").Append(layout.ToLowerInvariant()).Append('\n');
        // look's canonical mermaid spelling is camelCase handDrawn; normalize.
        if (look != null)
            sb.Append("  look: ")
              .Append(look.Equals("handdrawn", StringComparison.OrdinalIgnoreCase) ? "handDrawn" : "classic")
              .Append('\n');
        sb.Append("---\n").Append(mermaid);
        return sb.ToString();
    }

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Use one of: dagre (default layered) or elk (requires ESM elk loader).
  2. Leave layout unset to use mermaid's default (dagre).
  3. For elk, ensure the render path uses the ESM build (it does automatically when layout=elk).

Example fix

// before
layout=breadthfirst
// after
layout=elk
Defensive patterns

Strategy: validation

Validate before calling

static readonly HashSet<string> ValidLayouts = new(StringComparer.OrdinalIgnoreCase) { "dagre","elk" };
static string ValidateLayout(string layout) => ValidLayouts.Contains(layout ?? "") ? layout : throw new ArgumentException($"unknown layout '{layout}'");

Type guard

static bool IsValidLayout(string layout) => ValidLayouts.Contains(layout ?? "");

Try / catch

try { MermaidImageRenderer.ComposeSource(mermaid, null, layout, null); }
catch (ArgumentException ex) when (ex.Message.Contains("unknown diagram layout"))
{ /* default to null (dagre) or pick dagre/elk */ }

Prevention

When it happens

Trigger: Setting a diagram layout to 'breadthfirst', 'cose', 'circle', 'grid', 'force', or any value outside {dagre, elk}.

Common situations: Confusing mermaid's layouts with Cytoscape/d3 layout names; passing 'tree' or 'hierarchical' which are not mermaid layout ids; expecting a layout that requires a plugin not loaded.

Related errors


AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13). Data as JSON: /api/errors/5761e0680cf6d999. Report an issue: GitHub.