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

Meeting commenting configuration for disabling commenting mu

Error message

Meeting commenting configuration for disabling commenting must exist.

What it means

Thrown by DisableMeetingCommentingConfigurationCommandHandler when _meetingCommentingConfigurationRepository.GetByMeetingIdAsync returns null for the supplied MeetingId. A null result means no MeetingCommentingConfiguration aggregate exists for that meeting, so there is nothing to disable. The handler aborts with InvalidCommandException (surfaced as HTTP 400), because disabling commenting on a meeting that has no configuration is not a valid operation.

Source

Thrown at src/Modules/Meetings/Application/MeetingCommentingConfigurations/DisableMeetingCommentingConfiguration/DisableMeetingCommentingConfigurationCommandHandler.cs:34

        public DisableMeetingCommentingConfigurationCommandHandler(
            IMeetingCommentingConfigurationRepository meetingCommentingConfigurationRepository,
            IMeetingGroupRepository meetingGroupRepository,
            IMeetingRepository meetingRepository,
            IMemberContext memberContext)
        {
            _meetingCommentingConfigurationRepository = meetingCommentingConfigurationRepository;
            _meetingGroupRepository = meetingGroupRepository;
            _meetingRepository = meetingRepository;
            _memberContext = memberContext;
        }

        public async Task Handle(DisableMeetingCommentingConfigurationCommand command, CancellationToken cancellationToken)
        {
            var meetingCommentingConfiguration = await _meetingCommentingConfigurationRepository.GetByMeetingIdAsync(new MeetingId(command.MeetingId));
            if (meetingCommentingConfiguration == null)
            {
                throw new InvalidCommandException(["Meeting commenting configuration for disabling commenting must exist."]);
            }

            var meeting = await _meetingRepository.GetByIdAsync(new MeetingId(command.MeetingId));

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

            meetingCommentingConfiguration.DisableCommenting(_memberContext.MemberId, meetingGroup);
        }
    }
}

View on GitHub (pinned to 91c8ef24b4)

Solutions

  1. Confirm the MeetingId resolves to an existing meeting and that its commenting configuration row exists in the meeting_commenting_configurations table.
  2. If the configuration is genuinely absent, re-run the meeting creation flow so it is seeded, rather than calling disable.
  3. In the calling controller, query configuration existence first and return 404 instead of dispatching a command that will throw.
  4. Catch InvalidCommandException at the API boundary and map it to a 400/404 with a descriptive body.

Example fix

// before
await _commandDispatcher.SendAsync(new DisableMeetingCommentingConfigurationCommand(meetingId));

// after
var exists = await _meetingQueries.ConfigurationExistsForMeetingAsync(meetingId);
if (!exists) return NotFound("Commenting configuration not found for meeting.");
await _commandDispatcher.SendAsync(new DisableMeetingCommentingConfigurationCommand(meetingId));
Defensive patterns

Strategy: validation

Validate before calling

var exists = await _meetingQueries.ConfigurationExistsForMeetingAsync(meetingId);
if (!exists) return NotFound("Commenting configuration not found for meeting.");
await _commandDispatcher.SendAsync(new DisableMeetingCommentingConfigurationCommand(meetingId));

Type guard

public static bool IsValidMeetingId(DisableMeetingCommentingConfigurationCommand c) =>
    c.MeetingId != Guid.Empty;

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: Dispatching DisableMeetingCommentingConfigurationCommand with an empty/wrong/fabricated MeetingId, a meeting whose configuration row was deleted, or calling disable before the meeting-creation flow has committed the configuration insert.

Common situations: Admin UI exposes a 'disable comments' button for a meeting that failed initialization; integration tests pass a random Guid; a race condition dispatches disable in the same unit of work before the configuration is persisted.

Related errors


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