iOfficeAI/OfficeCLI · error · ArgumentException

Unknown chart preset '{value}'. Available: {string.Join(", "

Error message

Unknown chart preset '{value}'. Available: {string.Join(", ", ChartPresets.PresetNames)}.

What it means

Thrown by SetChartProperties when the 'preset', 'style.preset', or 'theme' key resolves to a name not registered in ChartPresets (the closed set: minimal, dark, corporate, magazine, dashboard, colorful, monochrome). The library applies a preset by recursively expanding its property dictionary before the rest of the Set call, so an unknown name cannot be silently skipped. Rejecting up front prevents a half-applied preset leaking into the chart XML.

Source

Thrown at src/officecli/Core/Chart/ChartHelper.Setter.cs:272

            // majortickmark/ticklabelpos setters so those can skip the now-hidden
            // axis; otherwise the hidden secondary catAx reappears after replay.
            if (lower is "secondaryaxis" or "secondary") return 1;
            if (lower is "title" or "legend" or "datalabels" or "labels") return 1;
            // axis-title TEXT must build the <c:title> element before axistitle.pPr
            // (order 2) replaces its paragraph properties.
            if (lower is "axistitle" or "vtitle" or "cattitle" or "htitle") return 1;
            return 2;
        }
        var ordered = properties.OrderBy(kv => PropOrder(kv.Key));
        foreach (var (key, value) in ordered)
        {
            switch (key.ToLowerInvariant())
            {
                case "preset" or "style.preset" or "theme":
                {
                    var presetProps = ChartPresets.GetPreset(value);
                    if (presetProps == null)
                        throw new ArgumentException(
                            $"Unknown chart preset '{value}'. Available: {string.Join(", ", ChartPresets.PresetNames)}.");
                    // Recursively apply preset properties
                    var presetUnsupported = SetChartProperties(chartPart, presetProps);
                    // Silently skip title.* properties when chart has no title —
                    // presets include title styling but charts may legitimately have no title
                    var hasTitle = chart.GetFirstChild<C.Title>() != null;
                    if (!hasTitle)
                        presetUnsupported.RemoveAll(k => k.StartsWith("title.", StringComparison.OrdinalIgnoreCase)
                            || (k.StartsWith("title", StringComparison.OrdinalIgnoreCase) && k.Length > 5));
                    unsupported.AddRange(presetUnsupported);
                    break;
                }

                case "title":
                    chart.RemoveAllChildren<C.Title>();
                    if (!string.IsNullOrEmpty(value) && !value.Equals("none", StringComparison.OrdinalIgnoreCase))
                    {
                        // CONSISTENCY(autoTitleDeleted-paired): setting a title back

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Spell the preset name exactly as one of: minimal, dark, corporate, magazine, dashboard, colorful, monochrome (or mono).
  2. Read the allowed list programmatically from ChartPresets.PresetNames before building your property dictionary.
  3. If you intended a custom look, do not use the preset key — set the individual properties (colors, gridlines, fonts) directly.

Example fix

// before
SetChartProperties(part, new() { ["preset"] = "miniml" });
// after
var name = "minimal";
if (!ChartPresets.PresetNames.Contains(name))
    throw new InvalidOperationException($"Unknown preset '{name}'");
SetChartProperties(part, new() { ["preset"] = name });
Defensive patterns

Strategy: validation

Validate before calling

static readonly HashSet<string> ChartPresetNames =
    new(ChartPresets.PresetNames, StringComparer.OrdinalIgnoreCase) { "mono" };

static bool IsValidPreset(string v) =>
    !string.IsNullOrWhiteSpace(v) && ChartPresetNames.Contains(v.Trim());

Type guard

static bool IsKnownPreset(string v) =>
    ChartPresets.PresetNames.Contains(v, StringComparer.OrdinalIgnoreCase)
    || v.Equals("mono", StringComparison.OrdinalIgnoreCase);

Try / catch

try { SetChartProperties(part, props); }
catch (ArgumentException ex) when (ex.Message.StartsWith("Unknown chart preset"))
{ /* log and surface available preset names to the user */ }

Prevention

When it happens

Trigger: Calling SetChartProperties with { ["preset"] = "miniml" } (typo), { ["theme"] = "dark2" }, or any value not in ChartPresets.PresetNames. The alias 'mono' is accepted for monochrome; no other aliases exist.

Common situations: Typos in config files or CLI flags preset=minimal; outdated docs referencing a preset name that was renamed/removed in a version change; copy-pasting a preset name from a different tool's vocabulary.

Related errors


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