{"record":{"id":"ce3160e76bb8714b","repo":"iOfficeAI/OfficeCLI","slug":"rid-property-is-required-for-chartex-pinned-rel","errorCode":null,"errorMessage":"'rid' property is required for chartex (pinned relationship id)","messagePattern":"'rid' property is required for chartex \\(pinned relationship id\\)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Add.cs","lineNumber":1211,"sourceCode":"            case \"chartex\":\n            {\n                // 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                }","sourceCodeStart":1193,"sourceCodeEnd":1229,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Add.cs#L1193-L1229","documentation":"chartEx is carried verbatim with pinned source relationship IDs (mirrors the pptx SmartArt pattern). The 'rid' property pins the rId the graphicFrame slice uses in the destination drawing so it resolves without rewriting. Without it the handler cannot wire the raw graphicFrame into the drawing. It is required.","triggerScenarios":"AddPart(..., \"chartex\", properties) where properties has no 'rid' key or a null value.","commonSituations":"Hand-authored batch missing the pinned rId; a dump→batch pipeline that did not emit rid; confusing rid with the chart's own internal rIds.","solutions":["Set properties[\"rid\"] to the source graphicFrame's r:id (e.g. \"rId3\").","Re-dump to obtain the pinned rid the emitter records.","Confirm the rid matches an rId that the raw-set graphicFrame will reference."],"exampleFix":"// before\nvar props = new Dictionary<string,string>{ [\"xml\"] = cxChartB64 };\nhandler.AddPart(\"/Sheet1\", \"chartex\", props);\n// after\nprops[\"rid\"] = \"rId3\";\nhandler.AddPart(\"/Sheet1\", \"chartex\", props);","handlingStrategy":"validation","validationCode":"if (string.IsNullOrEmpty(properties?.GetValueOrDefault(\"rid\")))\n    throw new InvalidOperationException(\"chartex requires a pinned 'rid'.\");","typeGuard":"static bool HasRid(Dictionary<string,string>? p) =>\n    !string.IsNullOrEmpty(p?.GetValueOrDefault(\"rid\"));","tryCatchPattern":"try { handler.AddPart(parent, \"chartex\", props); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"'rid' property is required for chartex\"))\n{ /* set props[\"rid\"] to the graphicFrame r:id, retry */ }","preventionTips":["Always emit rid alongside the chartEx graphicFrame in dump→batch.","Confirm rid appears in the raw-set graphicFrame's r:id attribute.","Re-dump to keep rid and xml consistent."],"tags":["excel","openxml","add-part","chartex","required-property"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}