iOfficeAI/OfficeCLI · error · ArgumentException

'rid' property is required for ole (pinned payload relations

Error message

'rid' property is required for ole (pinned payload relationship id)

What it means

The 'rid' property pins the relationship ID the payload part is registered under, which is referenced by the verbatim object-xml's <oleObject r:id=...>. Because the object-xml is carried verbatim, the rId must be supplied so the embed relationship and the child element agree. Required.

Source

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

                // Verbatim OLE carrier for dump→batch round-trip. Mirrors the
                // pptx add-part ole contract (pinned rIds + base64 payloads)
                // but is all-in-one: Excel's OLE anatomy spans the worksheet
                // (<oleObjects> child + embed/icon rels), the VML drawing
                // (anchor shape) and <legacyDrawing>, all of which must stay
                // consistent — so the handler wires everything here instead
                // of leaving XML splicing to a companion raw-set.
                // Props: rid + data (+content-type/extension) = payload part;
                // icon-rid + icon-data (+icon-content-type) = objectPr image;
                // vml-shape = the <v:shape> anchor XML verbatim;
                // object-xml = the <oleObjects> CHILD element verbatim
                // (mc:AlternateContent or bare oleObject, pinned rIds inside).
                var oleSheetName = parentPartPath.TrimStart('/');
                var oleWs = FindWorksheet(oleSheetName)
                    ?? throw new ArgumentException(
                        $"Sheet not found: {oleSheetName}. ole must be added under a sheet: add-part <file> /<SheetName> --type ole");
                properties ??= new Dictionary<string, string>();
                var oleRid = properties.GetValueOrDefault("rid")
                    ?? throw new ArgumentException("'rid' property is required for ole (pinned payload relationship id)");
                var oleDataB64 = properties.GetValueOrDefault("data")
                    ?? throw new ArgumentException("'data' property is required for ole (base64 payload bytes)");
                var oleObjectXml = properties.GetValueOrDefault("object-xml")
                    ?? throw new ArgumentException("'object-xml' property is required for ole (verbatim oleObjects child element)");
                byte[] oleBytes;
                try { oleBytes = Convert.FromBase64String(oleDataB64); }
                catch (FormatException) { throw new ArgumentException("add-part ole: 'data' is not valid base64"); }

                var oleCt = properties.GetValueOrDefault("content-type")
                    ?? "application/vnd.openxmlformats-officedocument.oleObject";
                var oleExt = properties.GetValueOrDefault("extension") ?? ".bin";
                if (!oleExt.StartsWith('.')) oleExt = "." + oleExt;

                // Kind comes from the dump (source part type), because content
                // type alone cannot classify legacy package formats (.xls
                // carries application/vnd.ms-excel, not an OOXML CT). Fallback
                // for hand-written batches that omit ole-kind: package iff the
                // CT is a non-oleObject openxmlformats CT.

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Set properties["rid"] to the rId used inside the object-xml (e.g. "rId4").
  2. Re-dump so rid and object-xml are emitted consistently.
  3. Confirm rid appears in the object-xml's r:id attribute.

Example fix

// before
var props = new Dictionary<string,string>{ ["data"] = b64, ["object-xml"] = objXml };
handler.AddPart("/Sheet1", "ole", props);
// after
props["rid"] = "rId4";
handler.AddPart("/Sheet1", "ole", props);
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrEmpty(properties?.GetValueOrDefault("rid")))
    throw new InvalidOperationException("ole requires a pinned payload 'rid'.");

Type guard

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

Try / catch

try { handler.AddPart(parent, "ole", props); }
catch (ArgumentException ex) when (ex.Message.Contains("'rid' property is required for ole"))
{ /* set props["rid"] to match object-xml's r:id, retry */ }

Prevention

When it happens

Trigger: AddPart(..., "ole", properties) where properties has no 'rid' key or a null value.

Common situations: Hand-authored batch missing the pinned rId; a dump that did not emit rid; confusing the payload rid with the icon-rid.

Related errors


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