{"record":{"id":"345ae8b344094291","repo":"iOfficeAI/OfficeCLI","slug":"pivottable-requires-source-property-e-g-source","errorCode":null,"errorMessage":"pivottable requires 'source' property (e.g. source=Sheet1!A1:D100)","messagePattern":"pivottable requires 'source' property \\(e\\.g\\. source=Sheet1!A1:D100\\)","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Add.Tables.cs","lineNumber":1666,"sourceCode":"        tableParts.Count = (uint)tableParts.Elements<TablePart>().Count();\n        SaveWorksheet(tblWorksheet);\n\n        var tblIdx = PathIndex.FromArrayIndex(tblWorksheet.TableDefinitionParts.ToList().IndexOf(tableDefPart));\n        return $\"/{tblSheetName}/table[{tblIdx}]\";\n    }\n\n    private string AddPivotTable(string parentPath, string type, InsertPosition? position, Dictionary<string, string> properties)\n    {\n        var index = position?.Index;\n        var ptSegments = parentPath.TrimStart('/').Split('/', 2);\n        var ptSheetName = ptSegments[0];\n        var ptWorksheet = FindWorksheet(ptSheetName)\n            ?? throw new ArgumentException($\"Sheet not found: {ptSheetName}\");\n\n        // Source: \"Sheet1!A1:D100\" or \"A1:D100\" (same sheet)\n        var sourceSpec = properties.GetValueOrDefault(\"source\", \"\")\n            ?? properties.GetValueOrDefault(\"src\", \"\")\n            ?? throw new ArgumentException(\"pivottable requires 'source' property (e.g. source=Sheet1!A1:D100)\");\n        if (string.IsNullOrEmpty(sourceSpec))\n            throw new ArgumentException(\"pivottable requires 'source' property (e.g. source=Sheet1!A1:D100)\");\n\n        // R8-7: incidental whitespace around the source spec or its\n        // components (\" Sheet1 ! A1:D10 \") is a common paste-from-docs\n        // artefact. Trim the whole string and both sides of the '!'\n        // split so the downstream sheet/range lookup sees clean values.\n        sourceSpec = sourceSpec.Trim();\n\n        // R8-3: external workbook refs such as [other.xlsx]Sheet1!A1:D10\n        // used to fall through to FindWorksheet and surface as the\n        // misleading \"Source sheet not found: [other.xlsx]Sheet1\".\n        // Detect the '[' prefix up front and throw a clear error so\n        // users know the feature is not supported rather than blaming\n        // a missing sheet.\n        if (sourceSpec.StartsWith(\"[\"))\n            throw new ArgumentException(\n                \"External workbook references are not supported in pivot source. \"","sourceCodeStart":1648,"sourceCodeEnd":1684,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Add.Tables.cs#L1648-L1684","documentation":"Thrown by AddPivotTable when neither a 'source' nor a 'src' property is present in the properties dictionary. The source range (e.g. Sheet1!A1:D100) is mandatory because it defines the pivot cache's source data; without it the pivot cannot be built. The null-coalescing expression throws when both GetValueOrDefault calls return null.","triggerScenarios":"Calling Add('/Report/pivottable', ...) with no source/src key at all, or with the keys misspelled (e.g. 'data', 'from').","commonSituations":"Forgetting the source argument, using an unsupported alias, or assuming the handler infers the source from the host sheet's used range.","solutions":["Add a 'source' property with an explicit range, e.g. source=Data!A1:D100.","For same-sheet sources, a bare range like source=A1:D100 is accepted.","Use the 'src' alias if preferred; both keys are checked."],"exampleFix":"// before\nadd /Report/pivottable\n// after\nadd /Report/pivottable --prop source=Data!A1:D100","handlingStrategy":"validation","validationCode":"// Ensure a pivot source is present before Add.\nif (!props.ContainsKey(\"source\") && !props.ContainsKey(\"src\"))\n    throw new InvalidOperationException(\"pivottable requires a 'source' property.\");","typeGuard":null,"tryCatchPattern":"try { handler.Add(parentPath, \"pivottable\", null, props); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"requires 'source' property\"))\n{ /* prompt for the source range and retry */ }","preventionTips":["Make 'source' a required field in any pivot-building UI.","Use 'source' or 'src'; other aliases are not accepted.","Default the source to the data sheet's used range when known."],"tags":["excel","pivot-table","validation","missing-property"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}