iOfficeAI/OfficeCLI · error · ArgumentException

'xml' property is required for chartex (base64 cx:chartSpace

Error message

'xml' property is required for chartex (base64 cx:chartSpace XML)

What it means

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.

Source

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

                // Extended (cx:) chart carrier for dump→batch round-trip.
                // chartEx has no semantic add vocabulary — waterfall/funnel/
                // sunburst charts are carried VERBATIM: the caller pins the
                // source rIds so the graphicFrame slice raw-set into the
                // drawing resolves without rewriting. Mirrors the pptx
                // SmartArt add-part pattern (pinned rIds + raw payload).
                // Props: rid (required), xml (base64 cx:chartSpace),
                // colors-rid/colors-xml, style-rid/style-xml (optional
                // sub-parts — Excel-authored chartEx always carries both;
                // dropping them dangles the main part's rels).
                var cxSheetName = parentPartPath.TrimStart('/');
                var cxWorksheet = FindWorksheet(cxSheetName)
                    ?? throw new ArgumentException(
                        $"Sheet not found: {cxSheetName}. chartex must be added under a sheet: add-part <file> /<SheetName> --type chartex");
                properties ??= new Dictionary<string, string>();
                var cxRid = properties.GetValueOrDefault("rid")
                    ?? throw new ArgumentException("'rid' property is required for chartex (pinned relationship id)");
                var cxXmlB64 = properties.GetValueOrDefault("xml")
                    ?? throw new ArgumentException("'xml' property is required for chartex (base64 cx:chartSpace XML)");

                var cxDrawingsPart = cxWorksheet.DrawingsPart
                    ?? cxWorksheet.AddNewPart<DrawingsPart>();
                if (cxDrawingsPart.WorksheetDrawing == null)
                {
                    cxDrawingsPart.WorksheetDrawing =
                        new DocumentFormat.OpenXml.Drawing.Spreadsheet.WorksheetDrawing();
                    cxDrawingsPart.WorksheetDrawing.Save();
                    if (GetSheet(cxWorksheet).GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.Drawing>() == null)
                    {
                        var cxDrawRelId = cxWorksheet.GetIdOfPart(cxDrawingsPart);
                        GetSheet(cxWorksheet).Append(
                            new DocumentFormat.OpenXml.Spreadsheet.Drawing { Id = cxDrawRelId });
                        SaveWorksheet(cxWorksheet);
                    }
                }

                var extChartPart = cxDrawingsPart.AddNewPart<ExtendedChartPart>(cxRid);

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Set properties["xml"] to Convert.ToBase64String of the cx:chartSpace part bytes.
  2. Re-dump so the base64 payload is captured from the source part.
  3. Verify the decoded bytes are valid XML before encoding.

Example fix

// before
var props = new Dictionary<string,string>{ ["rid"] = "rId3" };
handler.AddPart("/Sheet1", "chartex", props);
// after
props["xml"] = Convert.ToBase64String(
    File.ReadAllBytes("/unpack/xl/charts/chartEx1.xml"));
handler.AddPart("/Sheet1", "chartex", props);
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrEmpty(properties?.GetValueOrDefault("xml")))
    throw new InvalidOperationException("chartex requires base64 'xml' payload.");

Type guard

static bool HasXml(Dictionary<string,string>? p) =>
    !string.IsNullOrEmpty(p?.GetValueOrDefault("xml"));

Try / catch

try { handler.AddPart(parent, "chartex", props); }
catch (ArgumentException ex) when (ex.Message.Contains("'xml' property is required for chartex"))
{ /* encode the cx:chartSpace bytes, retry */ }

Prevention

When it happens

Trigger: AddPart(..., "chartex", properties) where properties has no 'xml' key or its value is null/empty.

Common situations: Hand-authored batch omitting the payload; a serialization layer that dropped the large base64 string; reusing a chart (non-extended) property bag.

Related errors


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