{"record":{"id":"b35339231437d8e3","repo":"MiniMax-AI/skills","slug":"document-has-no-main-part","errorCode":null,"errorMessage":"Document has no main part.","messagePattern":"Document has no main part\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"critical","filePath":"skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/CommentSynchronizer.cs","lineNumber":19,"sourceCode":"using DocumentFormat.OpenXml;\nusing DocumentFormat.OpenXml.Packaging;\nusing DocumentFormat.OpenXml.Wordprocessing;\n\nnamespace MiniMaxAIDocx.Core.OpenXml;\n\n/// <summary>\n/// Manages the 4-file comment system (comments.xml, commentsExtended.xml,\n/// commentsIds.xml, commentsExtensible.xml) plus document.xml markers.\n/// </summary>\npublic static class CommentSynchronizer\n{\n    /// <summary>\n    /// Adds a comment to the document, updating all required parts.\n    /// </summary>\n    public static int AddComment(WordprocessingDocument doc, string text, string author, string rangeBookmark)\n    {\n        var mainPart = doc.MainDocumentPart\n            ?? throw new InvalidOperationException(\"Document has no main part.\");\n\n        int commentId = GetNextCommentId(doc);\n\n        // Ensure comments part exists\n        var commentsPart = mainPart.WordprocessingCommentsPart\n            ?? mainPart.AddNewPart<WordprocessingCommentsPart>();\n\n        if (commentsPart.Comments == null)\n            commentsPart.Comments = new Comments();\n\n        // Create the comment\n        var comment = new Comment\n        {\n            Id = commentId.ToString(),\n            Author = author,\n            Date = DateTime.UtcNow,\n            Initials = author.Length > 0 ? author[..1].ToUpperInvariant() : \"A\"\n        };","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/MiniMax-AI/skills/blob/60aaae52bb2af8162732751a4332f62a5fef518b/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/CommentSynchronizer.cs#L1-L37","documentation":"`doc.MainDocumentPart ?? throw new InvalidOperationException(\"Document has no main part.\")` at the top of `CommentSynchronizer.AddComment`. `MainDocumentPart` (holding `word/document.xml`) is null on a document opened/created without one, so the method cannot place comment range markers in the body and aborts.","triggerScenarios":"Calling `AddComment` on a `WordprocessingDocument` created via `WordprocessingDocument.Create(...)` without a follow-up `AddMainDocumentPart()`, or on a malformed `.docx` package missing `word/document.xml`.","commonSituations":"Newly created documents that were never seeded with a main part, opening template/empty shells, or operating on a disposed/closed document handle.","solutions":["Seed the main part when creating: `var main = doc.AddMainDocumentPart(); main.Document = new Document(new Body());` before `AddComment`.","Open from a valid `.docx` and guard `if (doc.MainDocumentPart is null) { /* recreate from template */ }` first.","Ensure the document is not already disposed before calling."],"exampleFix":"// before\nusing var doc = WordprocessingDocument.Create(p, WordprocessingDocumentType.Document);\nCommentSynchronizer.AddComment(doc, \"note\", \"me\", \"bm\"); // throws\n\n// after\nusing var doc = WordprocessingDocument.Create(p, WordprocessingDocumentType.Document);\nvar main = doc.AddMainDocumentPart();\nmain.Document = new Document(new Body());\nCommentSynchronizer.AddComment(doc, \"note\", \"me\", \"bm\");","handlingStrategy":"validation","validationCode":"static void EnsureReady(WordprocessingDocument doc)\n{\n    if (doc.MainDocumentPart is null)\n    {\n        var main = doc.AddMainDocumentPart();\n        main.Document = new Document(new Body());\n    }\n}\n\n// call before AddComment\nEnsureReady(doc);\nint id = CommentSynchronizer.AddComment(doc, text, author, rangeBookmark);","typeGuard":"static bool IsDocumentReady(WordprocessingDocument doc) =>\n    doc.MainDocumentPart is not null;","tryCatchPattern":"try\n{\n    return CommentSynchronizer.AddComment(doc, text, author, rangeBookmark);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"no main part\"))\n{\n    var main = doc.AddMainDocumentPart();\n    main.Document = new Document(new Body());\n    return CommentSynchronizer.AddComment(doc, text, author, rangeBookmark);\n}","preventionTips":["Never call comment methods on a freshly created document without first seeding MainDocumentPart + a Document/Body.","Route document creation through a single factory that guarantees the main part exists.","Open from a valid `.docx` template rather than creating empty packages when you need comments.","Add a precondition check (`doc.MainDocumentPart is null`) and a descriptive error in your own wrapper."],"tags":["csharp","openxml","docx","document-part","comments"],"backgroundTag":null,"analyzedSha":"60aaae52bb2af8162732751a4332f62a5fef518b","analyzedAt":"2026-08-13T17:32:34.717Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}