{"record":{"id":"51a00118ee1ce8a6","repo":"MiniMax-AI/skills","slug":"document-has-no-comments-part","errorCode":null,"errorMessage":"Document has no comments part.","messagePattern":"Document has no comments part\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/CommentSynchronizer.cs","lineNumber":67,"sourceCode":"\n            body.Append(rangeStart);\n            body.Append(rangeEnd);\n            body.Append(new Paragraph(reference));\n        }\n\n        return commentId;\n    }\n\n    /// <summary>\n    /// Adds a reply to an existing comment.\n    /// </summary>\n    public static int AddReply(WordprocessingDocument doc, int parentCommentId, string text, string author)\n    {\n        var mainPart = doc.MainDocumentPart\n            ?? throw new InvalidOperationException(\"Document has no main part.\");\n\n        var commentsPart = mainPart.WordprocessingCommentsPart\n            ?? throw new InvalidOperationException(\"Document has no comments part.\");\n\n        int replyId = GetNextCommentId(doc);\n\n        var reply = new Comment\n        {\n            Id = replyId.ToString(),\n            Author = author,\n            Date = DateTime.UtcNow,\n            Initials = author.Length > 0 ? author[..1].ToUpperInvariant() : \"A\"\n        };\n        reply.Append(new Paragraph(new Run(new Text(text))));\n        commentsPart.Comments?.Append(reply);\n\n        // Link reply to parent via commentsExtended.xml\n        LinkReplyToParent(doc, replyId, parentCommentId);\n\n        return replyId;\n    }","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/MiniMax-AI/skills/blob/60aaae52bb2af8162732751a4332f62a5fef518b/skills/minimax-docx/scripts/dotnet/MiniMaxAIDocx.Core/OpenXml/CommentSynchronizer.cs#L49-L85","documentation":"`mainPart.WordprocessingCommentsPart ?? throw new InvalidOperationException(\"Document has no comments part.\")` in `AddReply`. Unlike `AddComment` (which lazily creates the comments part), `AddReply` requires an existing comments part to append the reply to a parent thread. If no comments exist yet, there is no parent to reply to, so the method refuses.","triggerScenarios":"Calling `AddReply(doc, parentCommentId, ...)` on a document that has never had `AddComment` called (so `WordprocessingCommentsPart` is null), or where the comments part was removed/corrupted.","commonSituations":"Replying before creating any top-level comment, operating on a document that lost its `word/comments.xml`, or calling AddReply against a `parentCommentId` that was never created.","solutions":["Create the parent comment first via `AddComment` (it bootstraps the comments part), then call `AddReply` with the returned id.","If the part genuinely should exist, verify the source `.docx` still contains `word/comments.xml`.","If you need a reply on an empty doc, call AddComment once first to initialize parts."],"exampleFix":"// before\nCommentSynchronizer.AddReply(doc, 1, \"reply\", \"me\"); // throws — no comments part\n\n// after\nint parentId = CommentSynchronizer.AddComment(doc, \"first\", \"me\", \"bm\");\nCommentSynchronizer.AddReply(doc, parentId, \"reply\", \"me\");","handlingStrategy":"validation","validationCode":"if (doc.MainDocumentPart?.WordprocessingCommentsPart is null)\n{\n    // no comments exist yet — create a parent first\n    int parentId = CommentSynchronizer.AddComment(doc, \"thread\", author, rangeBookmark);\n    CommentSynchronizer.AddReply(doc, parentId, replyText, author);\n}\nelse\n{\n    CommentSynchronizer.AddReply(doc, existingParentId, replyText, author);\n}","typeGuard":"static bool HasCommentsPart(WordprocessingDocument doc) =>\n    doc.MainDocumentPart?.WordprocessingCommentsPart is not null;","tryCatchPattern":"try\n{\n    return CommentSynchronizer.AddReply(doc, parentId, text, author);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"no comments part\"))\n{\n    // bootstrap by creating a parent comment, then retry\n    int newParent = CommentSynchronizer.AddComment(doc, \"(thread)\", author, \"bm\");\n    return CommentSynchronizer.AddReply(doc, newParent, text, author);\n}","preventionTips":["Remember AddReply requires an existing comments part; AddComment creates it.","Validate `parentCommentId` actually exists before replying.","Wrap comment workflows so the bootstrap (first AddComment) always precedes AddReply.","If loading an existing docx, confirm `word/comments.xml` is present before replying."],"tags":["csharp","openxml","docx","comments","validation"],"backgroundTag":null,"analyzedSha":"60aaae52bb2af8162732751a4332f62a5fef518b","analyzedAt":"2026-08-13T17:32:34.717Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}