{"record":{"id":"c8377d9d658412fa","repo":"iOfficeAI/OfficeCLI","slug":"cannot-embed-a-workbook-into-itself-the-source-fi","errorCode":null,"errorMessage":"Cannot embed a workbook into itself: the source file is the workbook being edited. Embed a different file, or make a copy of the source first.","messagePattern":"Cannot embed a workbook into itself: the source file is the workbook being edited\\. Embed a different file, or make a copy of the source first\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Add.Drawings.cs","lineNumber":87,"sourceCode":"        // empty legacy VmlDrawingPart and register the shapeId\n        // there so the relationship target exists.\n        var oleSheetSegs = parentPath.TrimStart('/').Split('/', 2);\n        var oleSheetName = oleSheetSegs[0];\n        var oleWorksheet = FindWorksheet(oleSheetName)\n            ?? throw new ArgumentException($\"Sheet not found: {oleSheetName}\");\n\n        var oleSrc = OfficeCli.Core.OleHelper.RequireSource(properties);\n        OfficeCli.Core.OleHelper.WarnOnUnknownOleProps(properties);\n\n        // Embedding the workbook into itself: the source is open/locked by this\n        // resident session, so the read yields 0 bytes and produces an empty\n        // OLE payload real Excel refuses (0x800A03EC). Reject up front.\n        try\n        {\n            if (!string.IsNullOrEmpty(oleSrc) && !string.IsNullOrEmpty(_filePath)\n                && string.Equals(Path.GetFullPath(oleSrc), Path.GetFullPath(_filePath),\n                    StringComparison.OrdinalIgnoreCase))\n                throw new ArgumentException(\n                    \"Cannot embed a workbook into itself: the source file is the workbook being edited. \"\n                    + \"Embed a different file, or make a copy of the source first.\");\n        }\n        catch (ArgumentException) { throw; }\n        catch { /* path canonicalization failed — fall through to normal read */ }\n\n        // CONSISTENCY(excel-ole-display): Excel OLE does not have a\n        // DrawAspect concept — worksheet objects are always shown as\n        // icons via objectPr/anchor, so 'display' would be a no-op.\n        // Set already rejects it; Add must too, for symmetry.\n        if (properties.ContainsKey(\"display\"))\n            throw new ArgumentException(\n                \"'display' property is not supported for Excel OLE \"\n                + \"(Excel always shows objects as icon). Remove --prop display.\");\n\n        // CONSISTENCY(ole-name): Word/PPT OLE accept --prop name=... and\n        // round-trip it via Get. SpreadsheetML x:oleObject has no Name\n        // attribute in the schema, so there is nowhere to persist it.","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Add.Drawings.cs#L69-L105","documentation":"Thrown when the OLE source file path resolves to the same absolute path as the workbook currently being edited (_filePath). The resident session holds the file open/locked, so reading it yields 0 bytes, producing an empty OLE payload that real Excel rejects with 0x800A03EC. The check uses Path.GetFullPath with OrdinalIgnoreCase comparison; a path-canonicalization failure is silently caught and falls through to the normal read path.","triggerScenarios":"Calling add /Sheet1 --type ole --src /path/to/currentworkbook.xlsx where the src path is the same file as the one open in the editing session. The ArgumentException is re-thrown explicitly (the catch (ArgumentException) { throw; } ensures it is not swallowed by the path-canonicalization fallback).","commonSituations":"User wants to embed a copy of the workbook into itself (e.g. as a template snapshot). User passes a relative path or symlink that resolves to the same absolute file. Automated pipeline that re-embeds the same file it is processing.","solutions":["Make a copy of the source workbook first and embed the copy: copy current.xlsx snapshot.xlsx, then --src snapshot.xlsx.","Embed a genuinely different file that is not the one being edited.","If you need a self-referential snapshot, export the data to a separate file first."],"exampleFix":"// before\nadd /Sheet1 --type ole --src report.xlsx\n// (report.xlsx IS the file being edited)\n// after (copy first, embed the copy)\n// cp report.xlsx report_snapshot.xlsx\nadd /Sheet1 --type ole --src report_snapshot.xlsx","handlingStrategy":"validation","validationCode":"// Detect self-embedding before calling OLE add\nvar src = OfficeCli.Core.OleHelper.RequireSource(properties);\nif (!string.IsNullOrEmpty(src) && !string.IsNullOrEmpty(handler.FilePath)\n    && string.Equals(Path.GetFullPath(src), Path.GetFullPath(handler.FilePath),\n        StringComparison.OrdinalIgnoreCase))\n    throw new InvalidOperationException(\n        \"Cannot embed a workbook into itself. Embed a different file or a copy.\");","typeGuard":null,"tryCatchPattern":"try { handler.AddOle(parentPath, properties); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"Cannot embed a workbook into itself\"))\n{\n    Console.Error.WriteLine($\"{ex.Message} Copy the source file first.\");\n}","preventionTips":["Never pass the file being edited as the OLE source.","Make a copy of the workbook first and embed the copy.","Compare source and destination paths with Path.GetFullPath before the add call.","In automated pipelines, snapshot the file to a temp path before embedding."],"tags":["excel","ole","self-embed","file-lock","validation"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}