{"record":{"id":"97f8e9b872039ae3","repo":"iOfficeAI/OfficeCLI","slug":"source-sheet-not-found-newsheetname","errorCode":null,"errorMessage":"Source sheet not found: {newSheetName}","messagePattern":"Source sheet not found: (.+?)","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/PivotTableHelper.Readback.cs","lineNumber":407,"sourceCode":"        if (newSourceSpec.Contains('!'))\n        {\n            var parts = newSourceSpec.Split('!', 2);\n            newSheetName = parts[0].Trim().Trim('\\'', '\"').Trim();\n            newRef = parts[1].Trim();\n        }\n        else\n        {\n            newSheetName = existingWsSource.Sheet?.Value ?? \"\";\n            newRef = newSourceSpec;\n        }\n\n        // Locate the source worksheet via the workbook part.\n        var workbookPart = pivotPart.GetParentParts().OfType<WorksheetPart>().FirstOrDefault()\n            ?.GetParentParts().OfType<WorkbookPart>().FirstOrDefault()\n            ?? throw new InvalidOperationException(\"Workbook part not reachable from pivot table part\");\n        var sheetEntry = workbookPart.Workbook?.Sheets?.Elements<Sheet>()\n            .FirstOrDefault(s => s.Name?.Value == newSheetName)\n            ?? throw new ArgumentException($\"Source sheet not found: {newSheetName}\");\n        if (sheetEntry.Id?.Value is not string srcRelId)\n            throw new InvalidOperationException(\"Source sheet has no relationship id\");\n        var sourceWsPart = workbookPart.GetPartById(srcRelId) as WorksheetPart\n            ?? throw new InvalidOperationException(\"Source sheet relationship does not resolve to a WorksheetPart\");\n\n        // Re-read source data from the new range.\n        var (headers, columnData, _) = ReadSourceData(sourceWsPart, newRef);\n        if (headers.Length == 0)\n            throw new ArgumentException(\"Source range has no data\");\n        if (columnData.Count == 0 || columnData[0].Length == 0)\n            throw new ArgumentException(\"Source range has no data rows\");\n\n        // R15-2: Before mutating any cache/pivot state, validate that existing\n        // row/col/value/filter field references still fit inside the new\n        // (possibly narrower) header list. A silent drop or index clamp here\n        // would leave the DataFields pointing past the rendered columnData,\n        // crashing RenderPivotIntoSheet with ArgumentOutOfRangeException.\n        // Prefer strict error over data loss: user must explicitly restate the","sourceCodeStart":389,"sourceCodeEnd":425,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/PivotTableHelper.Readback.cs#L389-L425","documentation":"Thrown by RefreshPivotCacheFromSource when re-binding an existing pivot to a new source range via Set source=. The sheet name (parsed from the spec before '!' e.g. 'Sheet1!A1:D10', or the cache's previously-stored sheet name if the spec has no '!') does not match any <Sheet> element in Workbook.Sheets. OOXML registers worksheet tabs there, so the pivot's WorksheetSource.Sheet must resolve to one of those entries by exact name match.","triggerScenarios":"Calling SetPivotTableProperties with source=Foo!A1:D10 where 'Foo' is not a tab in the workbook. Or calling source=A1:D10 (no sheet qualifier) when the existing cache's stored WorksheetSource.Sheet value is stale because the worksheet was renamed or deleted after the pivot was created.","commonSituations":"Renaming a worksheet after the pivot was created, leaving a stale sheet name in the cache source; typo in the CLI source= argument (wrong case, trailing space, quote mismatch); copy-pasting a source spec from a different workbook; sheet name contains leading/trailing whitespace that the Trim('\\\\\\'','\\\"') in the parser does not fully normalize.","solutions":["Verify the sheet name exists in the workbook with exact spelling and case (sheet names are case-sensitive in OOXML).","If the sheet was renamed, pass the new name explicitly in the source spec: source=NewSheetName!A1:D10.","If you want to keep the same sheet as the existing cache, use the bare-range form source=A1:D10 without a sheet qualifier so it reuses existingWsSource.Sheet.","List workbook sheets first (Get workbook sheets) to confirm the exact tab name before calling Set source=."],"exampleFix":"// before — sheet was renamed from 'Data' to 'Sales'\nSet pivot source=Data!A1:F100\n// after\nSet pivot source=Sales!A1:F100","handlingStrategy":"validation","validationCode":"// Before calling Set source=, verify the sheet exists\nvar sheets = workbookPart.Workbook?.Sheets?.Elements<Sheet>()\n    .Select(s => s.Name?.Value)\n    .Where(n => n != null)\n    .ToHashSet(StringComparer.Ordinal);\nvar specSheet = sourceSpec.Contains('!')\n    ? sourceSpec.Split('!', 2)[0].Trim().Trim('\\'', '\"').Trim()\n    : existingCacheSheetName;\nif (sheets == null || !sheets.Contains(specSheet))\n    throw new InvalidOperationException($\"Sheet '{specSheet}' not found. Available: {string.Join(\", \", sheets ?? new HashSet<string>())}\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["List workbook sheets before referencing one in a source spec.","Treat sheet names as case-sensitive — OOXML matches by Ordinal comparison.","If a sheet was renamed, update all source specs that reference it.","Use the bare-range form (A1:D10 without Sheet!) when you want to reuse the cache's existing sheet."],"tags":["pivot","excel","ooxml","source-range","sheet","set-property"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}