kgrzybek/modular-monolith-with-ddd · error · InvalidCommandException

Meeting for adding comment must exist.

Error message

Meeting for adding comment must exist.

What it means

Thrown by AddMeetingCommentCommandHandler when _meetingRepository.GetByIdAsync returns null for the supplied MeetingId. Commenting requires a target meeting aggregate; if none is found the command is rejected as InvalidCommandException (HTTP 400). The meeting is also used downstream to resolve the meeting group and commenting configuration.

Source

Thrown at src/Modules/Meetings/Application/MeetingComments/AddMeetingComment/AddMeetingCommentCommandHandler.cs:38

            IMeetingRepository meetingRepository,
            IMeetingCommentRepository meetingCommentRepository,
            IMeetingGroupRepository meetingGroupRepository,
            IMeetingCommentingConfigurationRepository meetingCommentingConfigurationRepository,
            IMemberContext memberContext)
        {
            _meetingGroupRepository = meetingGroupRepository;
            _meetingRepository = meetingRepository;
            _meetingCommentingConfigurationRepository = meetingCommentingConfigurationRepository;
            _meetingCommentRepository = meetingCommentRepository;
            _memberContext = memberContext;
        }

        public async Task<Guid> Handle(AddMeetingCommentCommand command, CancellationToken cancellationToken)
        {
            var meeting = await _meetingRepository.GetByIdAsync(new MeetingId(command.MeetingId));
            if (meeting == null)
            {
                throw new InvalidCommandException(["Meeting for adding comment must exist."]);
            }

            var meetingGroup = await _meetingGroupRepository.GetByIdAsync(meeting.GetMeetingGroupId());

            var meetingCommentingConfiguration = await _meetingCommentingConfigurationRepository.GetByMeetingIdAsync(new MeetingId(command.MeetingId));

            var meetingComment = meeting.AddComment(_memberContext.MemberId, command.Comment, meetingGroup, meetingCommentingConfiguration);

            await _meetingCommentRepository.AddAsync(meetingComment);

            return meetingComment.Id.Value;
        }
    }
}

View on GitHub (pinned to 91c8ef24b4)

Solutions

  1. Validate the MeetingId is a non-empty, existing meeting before allowing the user to comment.
  2. Refresh the client's meeting list so stale ids are not submitted.
  3. In the controller, check meeting existence via a query and return 404 instead of dispatching.
  4. Handle InvalidCommandException at the API boundary and return 400/404.

Example fix

// before
var commentId = await _commandDispatcher.SendAsync(new AddMeetingCommentCommand(meetingId, text));

// after
var meeting = await _meetingQueries.GetMeetingAsync(meetingId);
if (meeting is null) return NotFound("Meeting not found.");
var commentId = await _commandDispatcher.SendAsync(new AddMeetingCommentCommand(meetingId, text));
Defensive patterns

Strategy: validation

Validate before calling

var meeting = await _meetingQueries.GetMeetingAsync(meetingId);
if (meeting is null) return NotFound("Meeting not found.");
var id = await _commandDispatcher.SendAsync(new AddMeetingCommentCommand(meetingId, text));

Type guard

public static bool IsValidMeetingId(AddMeetingCommentCommand c) =>
    c.MeetingId != Guid.Empty && !string.IsNullOrWhiteSpace(c.Comment);

Try / catch

try { await _commandDispatcher.SendAsync(cmd); }
catch (InvalidCommandException ex) when (ex.Errors.Any(m => m.Contains("must exist")))
{ return NotFound(new { errors = ex.Errors }); }

Prevention

When it happens

Trigger: Posting AddMeetingCommentCommand with a MeetingId that does not correspond to any meeting: wrong/empty Guid, meeting not yet created, meeting in a different tenant/partition, or a stale client reference.

Common situations: Mobile/web client retains a meeting link after the meeting was deleted; concurrency where the comment is submitted during creation; tests using a fabricated id.

Related errors


AI-assisted analysis of kgrzybek/modular-monolith-with-ddd@91c8ef24b4 (2026-08-13). Data as JSON: /api/errors/9f8b9f42392e9b44. Report an issue: GitHub.