iOfficeAI/OfficeCLI · error · InvalidDataException

Part '{part.Uri.OriginalString}' contains no root element (o

Error message

Part '{part.Uri.OriginalString}' contains no root element (only an XML declaration, whitespace, or BOM). The package may be corrupt; investigate before treating output as data.

What it means

Thrown by ReadPartXml when an OpenXmlPart has no strongly-typed RootElement and its raw stream content strips down to nothing. The message explicitly warns the package may be corrupt and to investigate before treating output as data — distinguishing it from the milder zip-URI variants. InvalidDataException.

Source

Thrown at src/officecli/Core/RawXmlHelper.cs:1257

                    $"declaration, whitespace, or BOM).");
            return stripped;
        }
        finally
        {
            bclPkg.Close();
        }
    }

    public static string ReadPartXml(OpenXmlPart part)
    {
        if (part.RootElement is OpenXmlPartRootElement root && root != null)
            return root.OuterXml;
        using var stream = part.GetStream(FileMode.Open, FileAccess.Read);
        using var reader = new StreamReader(stream);
        var content = reader.ReadToEnd();
        var stripped = StripXmlProlog(content);
        if (stripped.Length == 0)
            throw new InvalidDataException(
                $"Part '{part.Uri.OriginalString}' contains no root element " +
                $"(only an XML declaration, whitespace, or BOM). The package " +
                $"may be corrupt; investigate before treating output as data.");
        return stripped;
    }

    private static string StripXmlProlog(string xml)
    {
        var s = xml.AsSpan().TrimStart();
        // Loop: handle multiple stacked prologs / BOMs (defensive — input may
        // be byte-concatenated from upstream tools or a corrupted package).
        while (s.Length > 0)
        {
            // BOM (U+FEFF). StreamReader normally consumes it but we may be
            // reading a re-encoded inner segment.
            if (s[0] == '') { s = s[1..].TrimStart(); continue; }

            // XML declaration: per spec must be `<?xml` followed by whitespace

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Inspect the part's bytes inside the zip to confirm corruption.
  2. Rebuild or re-save the document so every part has a valid root element.
  3. Do not catch-and-continue silently — the message flags potential corruption; log and halt for review.
Defensive patterns

Strategy: try-catch

Validate before calling

// Inspect a part's stream length before trusting it
using var s = part.GetStream(FileMode.Open, FileAccess.Read);
using var r = new StreamReader(s);
var len = r.ReadToEnd().Trim().Length;
if (len == 0) throw new InvalidDataException($"Part {part.Uri} is empty; investigate corruption.");

Try / catch

try { var xml = RawXmlHelper.ReadPartXml(part); }
catch (InvalidDataException ex) when (ex.Message.Contains("may be corrupt"))
{ /* do NOT treat as data — halt and investigate the package */ }

Prevention

When it happens

Trigger: Calling ReadPartXml on an untyped part (e.g. CustomXml) whose stream is empty, or on any OpenXmlPart whose RootElement is null and whose content is only a prolog/BOM/whitespace. ReadPartXml is reached from both the typed-part zip-URI path and direct part reads.

Common situations: A custom XML part was created but never populated, a package was corrupted in transit, or a part was written by a non-conformant tool. The 'investigate before treating output as data' wording signals a suspected integrity problem rather than a normal empty case.

Related errors


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