iOfficeAI/OfficeCLI · error · ArgumentException
add-part ole: 'data' is not valid base64
Error message
add-part ole: 'data' is not valid base64
What it means
The 'data' property was present but Convert.FromBase64String threw a FormatException — the string is not valid base64 (illegal characters, wrong length, or whitespace padding issues). The inner FormatException is swallowed and rethrown as an ArgumentException naming the field.
Solutions
- Regenerate data with Convert.ToBase64String on the raw payload bytes.
- Strip whitespace/newlines before passing if the source wrapped lines.
- Validate length is a multiple of 4 and uses the standard alphabet.
- If you have URL-safe base64, translate -_ to +/ and add padding.
Example fix
// before — pasted, line-wrapped blob fails to decode
props["data"] = wrappedPastedBlob;
// after — regenerate cleanly from the raw bytes
props["data"] = Convert.ToBase64String(
File.ReadAllBytes("/unpack/xl/embeddings/oleObject1.bin")); Defensive patterns
Strategy: try-catch
Validate before calling
try { Convert.FromBase64String(props["data"]); }
catch (FormatException) { /* strip whitespace, regenerate, or translate URL-safe base64 */ } Type guard
static bool IsValidBase64(string? s)
{ if (string.IsNullOrEmpty(s) || s.Length % 4 != 0) return false;
try { Convert.FromBase64String(s); return true; } catch { return false; } } Try / catch
try { handler.AddPart(parent, "ole", props); }
catch (ArgumentException ex) when (ex.Message.Contains("'data' is not valid base64"))
{ /* regenerate with Convert.ToBase64String, retry */ } Prevention
- Generate base64 with Convert.ToBase64String on raw bytes. Strip line wraps/whitespace from pasted blobs. Translate URL-safe (-_) to standard (+/) base64 and add padding.
When it happens
Trigger: data contains characters outside the base64 alphabet, has an invalid length (not a multiple of 4 after padding), embedded whitespace/newlines that some encoders reject, or was double-encoded.
Common situations: Manually pasting a base64 blob that got line-wrapped or truncated; a UTF-8 string mistaken for base64; base64 with URL-safe chars (-/_) instead of standard (+//); missing padding '='.
Related errors
- 'data' property is required for ole (base64 payload bytes)
- 'object-xml' property is required for ole (verbatim…
- 'rid' property is required for ole (pinned payload…
- Sheet not found: . ole must be added under a sheet…
- 'xml' property is required for chartex (base64…
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/d05423082b8a15c1.
Report an issue: GitHub.
Appendix: source
Thrown at src/officecli/Handlers/Excel/ExcelHandler.Add.cs:1283
// 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.
var oleKind = properties.GetValueOrDefault("ole-kind")
?? (oleCt.StartsWith(
"application/vnd.openxmlformats-officedocument.", StringComparison.OrdinalIgnoreCase)
&& !oleCt.Equals(
"application/vnd.openxmlformats-officedocument.oleObject", StringComparison.OrdinalIgnoreCase)
? "package" : "object");
// PartTypeInfo's target extension is dot-prefixed (".docx");View on GitHub (pinned to 1ced45e900)