iOfficeAI/OfficeCLI · error · ArgumentException

Unknown underline value '{shpUnder}'. Valid: single, double,

Error message

Unknown underline value '{shpUnder}'. Valid: single, double, none (true/false).

What it means

Thrown when the run-level underline property (`font.underline` or `underline`) is not one of the recognized tokens. The switch accepts single/sng and double/dbl and none/false, plus boolean true/single. Any other token — e.g. a numeric `1`, `wave`, `dotted`, or a localized word — hits the default arm and throws.

Source

Thrown at src/officecli/Handlers/Excel/ExcelHandler.Add.Drawings.cs:816

                ?? properties.GetValueOrDefault("font.bold");
            if (rawBold != null && IsTruthy(rawBold))
                rPr.Bold = true;

            string? rawItalic = properties.GetValueOrDefault("italic")
                ?? properties.GetValueOrDefault("font.italic");
            if (rawItalic != null && IsTruthy(rawItalic))
                rPr.Italic = true;

            if (properties.TryGetValue("font.underline", out var shpUnder)
                || properties.TryGetValue("underline", out shpUnder))
            {
                var uv = shpUnder.ToLowerInvariant();
                rPr.Underline = uv switch
                {
                    "true" or "single" or "sng" => Drawing.TextUnderlineValues.Single,
                    "double" or "dbl" => Drawing.TextUnderlineValues.Double,
                    "none" or "false" => Drawing.TextUnderlineValues.None,
                    _ => throw new ArgumentException(
                        $"Unknown underline value '{shpUnder}'. Valid: single, double, none (true/false).")
                };
            }

            // Fill (color) before fonts
            string? rawColor = properties.GetValueOrDefault("color")
                ?? properties.GetValueOrDefault("font.color");
            if (rawColor != null)
            {
                rPr.AppendChild(DrawingColorBuilder.BuildSolidFill(rawColor));
            }

            // Text-level effects for fill=none shapes
            var isNoFill = properties.TryGetValue("fill", out var f) && f.Equals("none", StringComparison.OrdinalIgnoreCase);
            if (isNoFill)
            {
                // CONSISTENCY(effect-list-schema-order): glow → outerShdw per CT_EffectList
                Drawing.Glow? txtGlowEl = null;

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Use single, double, or none (aliases sng, dbl, true/false are also accepted).
  2. Drop the underline property if no underline is desired (none is the implicit default).

Example fix

// before
add ./book.xlsx /Sheet1 shape --type textbox --prop font.text=Hi --prop underline=1
// after
add ./book.xlsx /Sheet1 shape --type textbox --prop font.text=Hi --prop underline=single
Defensive patterns

Strategy: type-guard

Validate before calling

var validUnderline = new[]{"single","sng","double","dbl","none","true","false"};
if (!validUnderline.Contains((underline ?? "").ToLowerInvariant()))
    throw new InvalidOperationException($"Invalid underline '{underline}'");

Type guard

static readonly HashSet<string> UnderlineTokens = new(StringComparer.OrdinalIgnoreCase)
    {"single","sng","double","dbl","none","true","false"};
static bool IsValidUnderline(string? v) => v is not null && UnderlineTokens.Contains(v);

Try / catch

try { handler.Add(...); }
catch (ArgumentException ex) when (ex.Message.Contains("Unknown underline"))
{ /* map to single/none as a safe default or reprompt */ }

Prevention

When it happens

Trigger: Passing `--prop font.underline=1` (numeric), `--prop underline=wavy`, `--prop underline=heavy`, or a style name from a different app (Word's underline vocabulary). The lookup is on `font.underline` first, then falls back to `underline`, so either key triggers the same switch.

Common situations: Assuming Excel/Word's full underline spectrum exists in Drawing ML run properties (it is only single/double/none here); using a boolean literal that isn't `true`/`false`.

Related errors


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