{"record":{"id":"2fb078be7822cbe6","repo":"iOfficeAI/OfficeCLI","slug":"xml-property-is-required-for-chartex-base64-cx","errorCode":null,"errorMessage":"'xml' property is required for chartex (base64 cx:chartSpace XML)","messagePattern":"'xml' property is required for chartex \\(base64 cx:chartSpace XML\\)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Add.cs","lineNumber":1213,"sourceCode":"                // Extended (cx:) chart carrier for dump→batch round-trip.\n                // chartEx has no semantic add vocabulary — waterfall/funnel/\n                // sunburst charts are carried VERBATIM: the caller pins the\n                // source rIds so the graphicFrame slice raw-set into the\n                // drawing resolves without rewriting. Mirrors the pptx\n                // SmartArt add-part pattern (pinned rIds + raw payload).\n                // Props: rid (required), xml (base64 cx:chartSpace),\n                // colors-rid/colors-xml, style-rid/style-xml (optional\n                // sub-parts — Excel-authored chartEx always carries both;\n                // dropping them dangles the main part's rels).\n                var cxSheetName = parentPartPath.TrimStart('/');\n                var cxWorksheet = FindWorksheet(cxSheetName)\n                    ?? throw new ArgumentException(\n                        $\"Sheet not found: {cxSheetName}. chartex must be added under a sheet: add-part <file> /<SheetName> --type chartex\");\n                properties ??= new Dictionary<string, string>();\n                var cxRid = properties.GetValueOrDefault(\"rid\")\n                    ?? throw new ArgumentException(\"'rid' property is required for chartex (pinned relationship id)\");\n                var cxXmlB64 = properties.GetValueOrDefault(\"xml\")\n                    ?? throw new ArgumentException(\"'xml' property is required for chartex (base64 cx:chartSpace XML)\");\n\n                var cxDrawingsPart = cxWorksheet.DrawingsPart\n                    ?? cxWorksheet.AddNewPart<DrawingsPart>();\n                if (cxDrawingsPart.WorksheetDrawing == null)\n                {\n                    cxDrawingsPart.WorksheetDrawing =\n                        new DocumentFormat.OpenXml.Drawing.Spreadsheet.WorksheetDrawing();\n                    cxDrawingsPart.WorksheetDrawing.Save();\n                    if (GetSheet(cxWorksheet).GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.Drawing>() == null)\n                    {\n                        var cxDrawRelId = cxWorksheet.GetIdOfPart(cxDrawingsPart);\n                        GetSheet(cxWorksheet).Append(\n                            new DocumentFormat.OpenXml.Spreadsheet.Drawing { Id = cxDrawRelId });\n                        SaveWorksheet(cxWorksheet);\n                    }\n                }\n\n                var extChartPart = cxDrawingsPart.AddNewPart<ExtendedChartPart>(cxRid);","sourceCodeStart":1195,"sourceCodeEnd":1231,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Add.cs#L1195-L1231","documentation":"The 'xml' property holds the base64-encoded cx:chartSpace payload for the chartEx part. It is required because there is no semantic construction path for extended charts — the raw part XML must be supplied. A missing/null value leaves nothing to write into the new chartEx part.","triggerScenarios":"AddPart(..., \"chartex\", properties) where properties has no 'xml' key or its value is null/empty.","commonSituations":"Hand-authored batch omitting the payload; a serialization layer that dropped the large base64 string; reusing a chart (non-extended) property bag.","solutions":["Set properties[\"xml\"] to Convert.ToBase64String of the cx:chartSpace part bytes.","Re-dump so the base64 payload is captured from the source part.","Verify the decoded bytes are valid XML before encoding."],"exampleFix":"// before\nvar props = new Dictionary<string,string>{ [\"rid\"] = \"rId3\" };\nhandler.AddPart(\"/Sheet1\", \"chartex\", props);\n// after\nprops[\"xml\"] = Convert.ToBase64String(\n    File.ReadAllBytes(\"/unpack/xl/charts/chartEx1.xml\"));\nhandler.AddPart(\"/Sheet1\", \"chartex\", props);","handlingStrategy":"validation","validationCode":"if (string.IsNullOrEmpty(properties?.GetValueOrDefault(\"xml\")))\n    throw new InvalidOperationException(\"chartex requires base64 'xml' payload.\");","typeGuard":"static bool HasXml(Dictionary<string,string>? p) =>\n    !string.IsNullOrEmpty(p?.GetValueOrDefault(\"xml\"));","tryCatchPattern":"try { handler.AddPart(parent, \"chartex\", props); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"'xml' property is required for chartex\"))\n{ /* encode the cx:chartSpace bytes, retry */ }","preventionTips":["Encode the cx:chartSpace part bytes with Convert.ToBase64String.","Validate the decoded bytes are well-formed XML before encoding.","Re-dump to capture the payload consistently."],"tags":["excel","openxml","add-part","chartex","required-property","base64"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}