iOfficeAI/OfficeCLI · error · ArgumentException

Invalid range '{spec}': end ({end}) must be >= start ({start

Error message

Invalid range '{spec}': end ({end}) must be >= start ({start}).

What it means

Thrown by ParseHelpers.ParseCharRange when a 'start:end' character-offset range has end < start. The function parses CLI/JSON 'range=' specs into 0-based half-open offset pairs (used by Word/PPT Set to format a targeted character span). Offsets must be non-negative integers and end must be >= start.

Source

Thrown at src/officecli/Core/ParseHelpers.cs:443

    /// <summary>
    /// Parse a "start:end" character-range spec into 0-based, half-open offsets.
    /// Colon separator mirrors the officecli range convention (Excel A1:B2).
    /// Shared by the pptx and docx run-range formatting paths so the two never
    /// diverge (CONSISTENCY(char-range)).
    /// </summary>
    public static (int Start, int End) ParseCharRange(string spec)
    {
        var parts = spec.Split(':');
        if (parts.Length != 2
            || !int.TryParse(parts[0].Trim(), CultureInfo.InvariantCulture, out var start)
            || !int.TryParse(parts[1].Trim(), CultureInfo.InvariantCulture, out var end))
            throw new ArgumentException(
                $"Invalid range '{spec}'. Expected 'start:end' with 0-based integer " +
                "character offsets (e.g. '6:11').");
        if (start < 0 || end < 0)
            throw new ArgumentException($"Invalid range '{spec}': offsets must be non-negative.");
        if (end < start)
            throw new ArgumentException($"Invalid range '{spec}': end ({end}) must be >= start ({start}).");
        return (start, end);
    }

    /// <summary>
    /// Parse a comma-separated list of "start:end" character ranges into 0-based,
    /// half-open offset pairs (e.g. "6:11,20:25" → [(6,11),(20,25)]). A single
    /// range needs no comma. This lets one range= command target several disjoint
    /// spans — the same shape find's format path produces from multiple matches —
    /// so range is a complete addressing alternative wherever the caller already
    /// knows the offsets. Order is preserved; the caller applies them (format-only
    /// run splitting does not shift character offsets, so any order is safe).
    /// </summary>
    public static List<(int Start, int End)> ParseCharRanges(string spec)
    {
        var result = new List<(int Start, int End)>();
        foreach (var seg in spec.Split(','))
        {
            var trimmed = seg.Trim();

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Swap the offsets so start <= end (e.g. range="6:11" instead of "11:6").
  2. If you derived the pair from a 'find' match, remember offsets are 0-based and half-open: start is the match start index, end is the start+length (or the match end index).
  3. For multiple spans use range="6:11,20:25" — ParseCharRanges sorts them ascending, but each individual range must still satisfy end>=start.

Example fix

// before
range="11:6"
// after
range="6:11"
Defensive patterns

Strategy: validation

Validate before calling

// Before calling ParseCharRange / ParseCharRanges, verify each 'start:end' pair:
static bool IsValidRangeSpec(string spec)
{
    foreach (var seg in spec.Split(','))
    {
        var t = seg.Trim();
        if (t.Length == 0) continue;
        var p = t.Split(':');
        if (p.Length != 2
            || !int.TryParse(p[0].Trim(), System.Globalization.CultureInfo.InvariantCulture, out var s)
            || !int.TryParse(p[1].Trim(), System.Globalization.CultureInfo.InvariantCulture, out var e)
            || s < 0 || e < 0 || e < s)
            return false;
    }
    return true;
}

Prevention

When it happens

Trigger: Calling PowerPointHandler.Set or WordHandler.Set with a 'range' property whose start offset exceeds the end offset, e.g. range="11:6" or range="20:5". ParseCharRange splits on ':', parses both halves as int, then checks end < start.

Common situations: Swapping start/end when hand-deriving offsets from a 'find' match; assuming the range is inclusive-right and subtracting one from the end (making end=start-1); off-by-one when converting 1-based visual positions to 0-based offsets.

Related errors


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