iOfficeAI/OfficeCLI · error · ArgumentException

Sheet not found: {afSheetName}

Error message

Sheet not found: {afSheetName}

What it means

Thrown by AddAutoFilter when FindWorksheet(afSheetName) returns null. afSheetName is the first segment of parentPath after trimming '/'. Same plain 'Sheet not found: <name>' inline form used by the comment/validation adders.

Source

Thrown at src/officecli/Handlers/Excel/ExcelHandler.Add.Tables.cs:721

        dvs.AppendChild(dv);
        dvs.Count = (uint)dvs.Elements<DataValidation>().Count();

        SaveWorksheet(dvWorksheet);
        var dvIndex = PathIndex.FromArrayIndex(dvs.Elements<DataValidation>().ToList().IndexOf(dv));
        // CONSISTENCY(path-segment-naming): the path segment must match the
        // type name the caller used in `add` (`dataValidation`). The legacy
        // `/validation[N]` form remains accepted by Get / Set / Remove as an
        // alias for back-compat (R7-bt-6).
        return $"/{dvSheetName}/dataValidation[{dvIndex}]";
    }

    private string AddAutoFilter(string parentPath, string type, InsertPosition? position, Dictionary<string, string> properties)
    {
        var index = position?.Index;
        var afSegments = parentPath.TrimStart('/').Split('/', 2);
        var afSheetName = afSegments[0];
        var afWorksheet = FindWorksheet(afSheetName)
            ?? throw new ArgumentException($"Sheet not found: {afSheetName}");

        // CONSISTENCY(tracking-rebind): the criteriaN.OP loop below iterates
        // properties via foreach over the static Dictionary<,> type, which
        // bypasses TrackingPropertyDictionary's comparer. Mark every
        // criteriaN.OP key (and `range`) as consumed up-front so they
        // don't surface as false unsupported_property warnings. Keys that
        // don't match either pattern fall through to the existing UNSUPPORTED
        // path naturally.
        if (properties is OfficeCli.Core.TrackingPropertyDictionary afTracking)
        {
            var consumed = properties.Keys
                .Where(k => string.Equals(k, "range", StringComparison.OrdinalIgnoreCase)
                    || Regex.IsMatch(k, @"^criteria\d+\.[A-Za-z]+$"))
                .ToList();
            afTracking.MarkAllConsumed(consumed);
        }

        var afRange = properties.GetValueOrDefault("range")

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Verify against handler.GetDumpSheetNames() and use the exact name.
  2. Correct the first parentPath segment (case-insensitive match).
  3. Create the sheet first if it is genuinely missing.

Example fix

// before
handler.Add("/Data2", "autofilter", null, new() { ["range"] = "A1:F100" });
// after
handler.Add("/Data", "autofilter", null, new() { ["range"] = "A1:F100" });
Defensive patterns

Strategy: validation

Validate before calling

var sheet = parentPath.TrimStart('/').Split('/', 2)[0];
if (!handler.GetDumpSheetNames()
        .Any(n => n.Equals(sheet, StringComparison.OrdinalIgnoreCase)))
    throw new InvalidOperationException($"No sheet '{sheet}'. Available: " +
        string.Join(", ", handler.GetDumpSheetNames()));

Prevention

When it happens

Trigger: Call Add type "autofilter" with a parentPath whose first segment names no worksheet, e.g. "/Data2" when the sheet is "Data".

Common situations: Sheet-name typo; sheet renamed/deleted; path copied from another workbook; index-based sheet reference that did not resolve.

Related errors


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