{"record":{"id":"d05423082b8a15c1","repo":"iOfficeAI/OfficeCLI","slug":"add-part-ole-data-is-not-valid-base64","errorCode":null,"errorMessage":"add-part ole: 'data' is not valid base64","messagePattern":"add-part ole: 'data' is not valid base64","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Add.cs","lineNumber":1283,"sourceCode":"                // Props: rid + data (+content-type/extension) = payload part;\n                // icon-rid + icon-data (+icon-content-type) = objectPr image;\n                // vml-shape = the <v:shape> anchor XML verbatim;\n                // object-xml = the <oleObjects> CHILD element verbatim\n                // (mc:AlternateContent or bare oleObject, pinned rIds inside).\n                var oleSheetName = parentPartPath.TrimStart('/');\n                var oleWs = FindWorksheet(oleSheetName)\n                    ?? throw new ArgumentException(\n                        $\"Sheet not found: {oleSheetName}. ole must be added under a sheet: add-part <file> /<SheetName> --type ole\");\n                properties ??= new Dictionary<string, string>();\n                var oleRid = properties.GetValueOrDefault(\"rid\")\n                    ?? throw new ArgumentException(\"'rid' property is required for ole (pinned payload relationship id)\");\n                var oleDataB64 = properties.GetValueOrDefault(\"data\")\n                    ?? throw new ArgumentException(\"'data' property is required for ole (base64 payload bytes)\");\n                var oleObjectXml = properties.GetValueOrDefault(\"object-xml\")\n                    ?? throw new ArgumentException(\"'object-xml' property is required for ole (verbatim oleObjects child element)\");\n                byte[] oleBytes;\n                try { oleBytes = Convert.FromBase64String(oleDataB64); }\n                catch (FormatException) { throw new ArgumentException(\"add-part ole: 'data' is not valid base64\"); }\n\n                var oleCt = properties.GetValueOrDefault(\"content-type\")\n                    ?? \"application/vnd.openxmlformats-officedocument.oleObject\";\n                var oleExt = properties.GetValueOrDefault(\"extension\") ?? \".bin\";\n                if (!oleExt.StartsWith('.')) oleExt = \".\" + oleExt;\n\n                // Kind comes from the dump (source part type), because content\n                // type alone cannot classify legacy package formats (.xls\n                // carries application/vnd.ms-excel, not an OOXML CT). Fallback\n                // for hand-written batches that omit ole-kind: package iff the\n                // CT is a non-oleObject openxmlformats CT.\n                var oleKind = properties.GetValueOrDefault(\"ole-kind\")\n                    ?? (oleCt.StartsWith(\n                            \"application/vnd.openxmlformats-officedocument.\", StringComparison.OrdinalIgnoreCase)\n                        && !oleCt.Equals(\n                            \"application/vnd.openxmlformats-officedocument.oleObject\", StringComparison.OrdinalIgnoreCase)\n                        ? \"package\" : \"object\");\n                // PartTypeInfo's target extension is dot-prefixed (\".docx\");","sourceCodeStart":1265,"sourceCodeEnd":1301,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Add.cs#L1265-L1301","documentation":"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.","triggerScenarios":"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.","commonSituations":"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 '='.","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."],"exampleFix":"// before — pasted, line-wrapped blob fails to decode\nprops[\"data\"] = wrappedPastedBlob;\n// after — regenerate cleanly from the raw bytes\nprops[\"data\"] = Convert.ToBase64String(\n    File.ReadAllBytes(\"/unpack/xl/embeddings/oleObject1.bin\"));","handlingStrategy":"try-catch","validationCode":"try { Convert.FromBase64String(props[\"data\"]); }\ncatch (FormatException) { /* strip whitespace, regenerate, or translate URL-safe base64 */ }","typeGuard":"static bool IsValidBase64(string? s)\n{ if (string.IsNullOrEmpty(s) || s.Length % 4 != 0) return false;\n try { Convert.FromBase64String(s); return true; } catch { return false; } }","tryCatchPattern":"try { handler.AddPart(parent, \"ole\", props); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"'data' is not valid base64\"))\n{ /* regenerate with Convert.ToBase64String, retry */ }","preventionTips":["Generate base64 with Convert.ToBase64String on raw bytes.\nStrip line wraps/whitespace from pasted blobs.\nTranslate URL-safe (-_) to standard (+/) base64 and add padding."],"tags":["excel","openxml","add-part","ole","base64"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}