iOfficeAI/OfficeCLI · error · ArgumentException

Cannot embed a workbook into itself: the source file is the

Error message

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.

What it means

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.

Source

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

        // empty legacy VmlDrawingPart and register the shapeId
        // there so the relationship target exists.
        var oleSheetSegs = parentPath.TrimStart('/').Split('/', 2);
        var oleSheetName = oleSheetSegs[0];
        var oleWorksheet = FindWorksheet(oleSheetName)
            ?? throw new ArgumentException($"Sheet not found: {oleSheetName}");

        var oleSrc = OfficeCli.Core.OleHelper.RequireSource(properties);
        OfficeCli.Core.OleHelper.WarnOnUnknownOleProps(properties);

        // Embedding the workbook into itself: the source is open/locked by this
        // resident session, so the read yields 0 bytes and produces an empty
        // OLE payload real Excel refuses (0x800A03EC). Reject up front.
        try
        {
            if (!string.IsNullOrEmpty(oleSrc) && !string.IsNullOrEmpty(_filePath)
                && string.Equals(Path.GetFullPath(oleSrc), Path.GetFullPath(_filePath),
                    StringComparison.OrdinalIgnoreCase))
                throw new ArgumentException(
                    "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.");
        }
        catch (ArgumentException) { throw; }
        catch { /* path canonicalization failed — fall through to normal read */ }

        // CONSISTENCY(excel-ole-display): Excel OLE does not have a
        // DrawAspect concept — worksheet objects are always shown as
        // icons via objectPr/anchor, so 'display' would be a no-op.
        // Set already rejects it; Add must too, for symmetry.
        if (properties.ContainsKey("display"))
            throw new ArgumentException(
                "'display' property is not supported for Excel OLE "
                + "(Excel always shows objects as icon). Remove --prop display.");

        // CONSISTENCY(ole-name): Word/PPT OLE accept --prop name=... and
        // round-trip it via Get. SpreadsheetML x:oleObject has no Name
        // attribute in the schema, so there is nowhere to persist it.

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Make a copy of the source workbook first and embed the copy: copy current.xlsx snapshot.xlsx, then --src snapshot.xlsx.
  2. Embed a genuinely different file that is not the one being edited.
  3. If you need a self-referential snapshot, export the data to a separate file first.

Example fix

// before
add /Sheet1 --type ole --src report.xlsx
// (report.xlsx IS the file being edited)
// after (copy first, embed the copy)
// cp report.xlsx report_snapshot.xlsx
add /Sheet1 --type ole --src report_snapshot.xlsx
Defensive patterns

Strategy: validation

Validate before calling

// Detect self-embedding before calling OLE add
var src = OfficeCli.Core.OleHelper.RequireSource(properties);
if (!string.IsNullOrEmpty(src) && !string.IsNullOrEmpty(handler.FilePath)
    && string.Equals(Path.GetFullPath(src), Path.GetFullPath(handler.FilePath),
        StringComparison.OrdinalIgnoreCase))
    throw new InvalidOperationException(
        "Cannot embed a workbook into itself. Embed a different file or a copy.");

Try / catch

try { handler.AddOle(parentPath, properties); }
catch (ArgumentException ex) when (ex.Message.Contains("Cannot embed a workbook into itself"))
{
    Console.Error.WriteLine($"{ex.Message} Copy the source file first.");
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


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