iOfficeAI/OfficeCLI · error · ArgumentException

Invalid legend position '{value}'. Valid: none, top, bottom,

Error message

Invalid legend position '{value}'. Valid: none, top, bottom, left, right, topRight (or use 'none'/'false' to hide the legend).

What it means

Thrown by ParseLegendPosition (ChartHelper.SetterHelpers.cs:40) when the legend position string, after SchemaKeyNormalizer.Normalize (which strips dash/underscore separators and lowercases), does not match top/t, bottom/b, left/l, right/r, or topright/tr. The method is reached only after the caller has already handled 'none'/'false' (legend removal), so any remaining unknown token is a genuine error. It exists because the legacy code silently coerced unknown tokens to 'bottom', producing a contradictory success message while the file carried legend=bottom (R34-1).

Source

Thrown at src/officecli/Core/Chart/ChartHelper.SetterHelpers.cs:40

    /// "Updated: legend=hidden" success message while the file actually
    /// carried legend=bottom (R34-1). Caller should already have handled
    /// "none" / "false" (legend removal) before reaching here.
    /// </summary>
    internal static C.LegendPositionValues ParseLegendPosition(string value)
    {
        // CONSISTENCY(legend-separator-normalize): accept dash AND underscore
        // as separators (`top-right`, `top_right`, `TOP_RIGHT`) by stripping
        // both before comparison. Without this, `TOP_RIGHT` threw while
        // `top-right` succeeded — punctuation variants should be uniform.
        var norm = SchemaKeyNormalizer.Normalize(value);
        return norm switch
        {
            "top" or "t" => C.LegendPositionValues.Top,
            "bottom" or "b" => C.LegendPositionValues.Bottom,
            "left" or "l" => C.LegendPositionValues.Left,
            "right" or "r" => C.LegendPositionValues.Right,
            "topright" or "tr" => C.LegendPositionValues.TopRight,
            _ => throw new ArgumentException(
                $"Invalid legend position '{value}'. " +
                "Valid: none, top, bottom, left, right, topRight " +
                "(or use 'none'/'false' to hide the legend)."),
        };
    }

    // ==================== Tick Mark Helpers ====================

    internal static C.TickMarkValues ParseTickMark(string value)
    {
        return value.ToLowerInvariant() switch
        {
            "none" or "false" => C.TickMarkValues.None,
            "in" or "inside" => C.TickMarkValues.Inside,
            "out" or "outside" => C.TickMarkValues.Outside,
            "cross" or "both" => C.TickMarkValues.Cross,
            _ => throw new ArgumentException(
                $"Invalid tick mark value '{value}'. Valid values: none, in, out, cross.")

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Use one of: top, bottom, left, right, topRight (or aliases t/b/l/r/tr).
  2. To hide the legend, use 'none' or 'false' — those are handled before this parser and never reach it.
  3. If passing a compound like 'top-right', note SchemaKeyNormalizer already strips dashes/underscores, so 'top-right' works but 'top left' (space) does not.

Example fix

// before
legend=top-left
// after
legend=topLeft
Defensive patterns

Strategy: validation

Validate before calling

static readonly Dictionary<string,string> LegendPositions = new(StringComparer.OrdinalIgnoreCase)
{ ["top"]="top",["t"]="top",["bottom"]="bottom",["b"]="bottom",["left"]="left",["l"]="left",["right"]="right",["r"]="right",["topright"]="topRight",["tr"]="topRight" };
static string ResolveLegendPosition(string v) => LegendPositions.TryGetValue(v ?? "", out var p) ? p : throw new ArgumentException($"invalid legend position '{v}'");

Type guard

static bool IsValidLegendPosition(string v) => LegendPositions.ContainsKey(v ?? "");

Try / catch

try { /* set chart legend=... */ }
catch (ArgumentException ex) when (ex.Message.Contains("Invalid legend position"))
{ /* prompt user with the 5 valid positions */ }

Prevention

When it happens

Trigger: Setting legend=<position> to a token that is not top/bottom/left/right/topright or their single-letter aliases, e.g. 'top-left', 'center', 'inside', 'tr' misspelled, 'northeast'.

Common situations: Confusing PowerPoint's 'Top Left'/'Bottom Center' UI labels with OOXML's five-position enum; passing a multi-word position like 'top left' that normalize does not collapse; copying 'l' vs 'r' single letters incorrectly.

Related errors


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