{"record":{"id":"8075e7c0af7bf323","repo":"kgrzybek/modular-monolith-with-ddd","slug":"to-add-like-the-comment-must-exist","errorCode":null,"errorMessage":"To add like the comment must exist.","messagePattern":"To add like the comment must exist\\.","errorType":"validation","errorClass":"InvalidCommandException","httpStatus":400,"severity":"error","filePath":"src/Modules/Meetings/Application/MeetingComments/AddMeetingCommentLike/AddMeetingCommentLikeCommandHandler.cs","lineNumber":35,"sourceCode":"\r\n        public AddMeetingCommentLikeCommandHandler(\r\n            IMeetingCommentRepository meetingCommentRepository,\r\n            IMeetingMemberCommentLikesRepository meetingMemberCommentLikesRepository,\r\n            IMemberContext memberContext,\r\n            ISqlConnectionFactory sqlConnectionFactory)\r\n        {\r\n            _meetingCommentRepository = meetingCommentRepository;\r\n            _memberContext = memberContext;\r\n            _sqlConnectionFactory = sqlConnectionFactory;\r\n            _meetingMemberCommentLikesRepository = meetingMemberCommentLikesRepository;\r\n        }\r\n\r\n        public async Task Handle(AddMeetingCommentLikeCommand request, CancellationToken cancellationToken)\r\n        {\r\n            var meetingComment = await _meetingCommentRepository.GetByIdAsync(new MeetingCommentId(request.MeetingCommentId));\r\n            if (meetingComment == null)\r\n            {\r\n                throw new InvalidCommandException([\"To add like the comment must exist.\"]);\r\n            }\r\n\r\n            var connection = _sqlConnectionFactory.GetOpenConnection();\r\n            var likerMeetingGroupMemberData = await MembersQueryHelper.GetMeetingGroupMember(_memberContext.MemberId, meetingComment.GetMeetingId(), connection);\r\n\r\n            var meetingMemeberCommentLikesCount = await _meetingMemberCommentLikesRepository.CountMemberCommentLikesAsync(\r\n                    _memberContext.MemberId,\r\n                    new MeetingCommentId(request.MeetingCommentId));\r\n\r\n            var like = meetingComment.Like(_memberContext.MemberId, likerMeetingGroupMemberData, meetingMemeberCommentLikesCount);\r\n\r\n            await _meetingMemberCommentLikesRepository.AddAsync(like);\r\n        }\r\n    }\r\n}","sourceCodeStart":17,"sourceCodeEnd":50,"githubUrl":"https://github.com/kgrzybek/modular-monolith-with-ddd/blob/91c8ef24b4cb6ef558c95d8267fa07d68c7059f8/src/Modules/Meetings/Application/MeetingComments/AddMeetingCommentLike/AddMeetingCommentLikeCommandHandler.cs#L17-L50","documentation":"Thrown by AddMeetingCommentLikeCommandHandler when _meetingCommentRepository.GetByIdAsync returns null for the supplied MeetingCommentId. A like must attach to an existing comment, so a missing comment aborts the command with InvalidCommandException (HTTP 400).","triggerScenarios":"Dispatching AddMeetingCommentLikeCommand for a comment id that does not exist: wrong Guid, comment was removed, reply-vs-comment id confusion, or a stale client reference.","commonSituations":"User likes a comment that was just deleted by its author; race between render and like; client passes the meeting id instead of the comment id.","solutions":["Confirm the MeetingCommentId refers to an existing, non-removed comment.","Ensure the client sends the comment id, not the meeting or reply id.","Pre-check comment existence in the controller and return 404.","Map InvalidCommandException to a 400/404 at the API boundary."],"exampleFix":"// before\nawait _commandDispatcher.SendAsync(new AddMeetingCommentLikeCommand(commentId));\n\n// after\nvar comment = await _meetingQueries.GetCommentAsync(commentId);\nif (comment is null) return NotFound(\"Comment not found.\");\nawait _commandDispatcher.SendAsync(new AddMeetingCommentLikeCommand(commentId));","handlingStrategy":"validation","validationCode":"var comment = await _meetingQueries.GetCommentAsync(commentId);\nif (comment is null) return NotFound(\"Comment not found.\");\nawait _commandDispatcher.SendAsync(new AddMeetingCommentLikeCommand(commentId));","typeGuard":"public static bool IsValidCommentId(AddMeetingCommentLikeCommand c) =>\n    c.MeetingCommentId != Guid.Empty;","tryCatchPattern":"try { await _commandDispatcher.SendAsync(cmd); }\ncatch (InvalidCommandException ex) when (ex.Errors.Any(m => m.Contains(\"must exist\")))\n{ return NotFound(new { errors = ex.Errors }); }","preventionTips":["Pass the comment id, never the meeting id, when liking.","Hide the like control once a comment is reported removed.","Guard against double-like dispatch (also avoids duplicate-like business rule)."],"tags":["meetings","comments","likes","not-found","invalid-command-exception","command-handler"],"backgroundTag":null,"analyzedSha":"91c8ef24b4cb6ef558c95d8267fa07d68c7059f8","analyzedAt":"2026-08-13T17:18:16.571Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}