{"record":{"id":"7826a24e1141bfe2","repo":"kgrzybek/modular-monolith-with-ddd","slug":"meeting-commenting-configuration-for-disabling-com","errorCode":null,"errorMessage":"Meeting commenting configuration for disabling commenting must exist.","messagePattern":"Meeting commenting configuration for disabling commenting must exist\\.","errorType":"validation","errorClass":"InvalidCommandException","httpStatus":400,"severity":"error","filePath":"src/Modules/Meetings/Application/MeetingCommentingConfigurations/DisableMeetingCommentingConfiguration/DisableMeetingCommentingConfigurationCommandHandler.cs","lineNumber":34,"sourceCode":"\r\n        public DisableMeetingCommentingConfigurationCommandHandler(\r\n            IMeetingCommentingConfigurationRepository meetingCommentingConfigurationRepository,\r\n            IMeetingGroupRepository meetingGroupRepository,\r\n            IMeetingRepository meetingRepository,\r\n            IMemberContext memberContext)\r\n        {\r\n            _meetingCommentingConfigurationRepository = meetingCommentingConfigurationRepository;\r\n            _meetingGroupRepository = meetingGroupRepository;\r\n            _meetingRepository = meetingRepository;\r\n            _memberContext = memberContext;\r\n        }\r\n\r\n        public async Task Handle(DisableMeetingCommentingConfigurationCommand command, CancellationToken cancellationToken)\r\n        {\r\n            var meetingCommentingConfiguration = await _meetingCommentingConfigurationRepository.GetByMeetingIdAsync(new MeetingId(command.MeetingId));\r\n            if (meetingCommentingConfiguration == null)\r\n            {\r\n                throw new InvalidCommandException([\"Meeting commenting configuration for disabling commenting must exist.\"]);\r\n            }\r\n\r\n            var meeting = await _meetingRepository.GetByIdAsync(new MeetingId(command.MeetingId));\r\n\r\n            var meetingGroup = await _meetingGroupRepository.GetByIdAsync(meeting.GetMeetingGroupId());\r\n\r\n            meetingCommentingConfiguration.DisableCommenting(_memberContext.MemberId, meetingGroup);\r\n        }\r\n    }\r\n}","sourceCodeStart":16,"sourceCodeEnd":44,"githubUrl":"https://github.com/kgrzybek/modular-monolith-with-ddd/blob/91c8ef24b4cb6ef558c95d8267fa07d68c7059f8/src/Modules/Meetings/Application/MeetingCommentingConfigurations/DisableMeetingCommentingConfiguration/DisableMeetingCommentingConfigurationCommandHandler.cs#L16-L44","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Confirm the MeetingId resolves to an existing meeting and that its commenting configuration row exists in the meeting_commenting_configurations table.","If the configuration is genuinely absent, re-run the meeting creation flow so it is seeded, rather than calling disable.","In the calling controller, query configuration existence first and return 404 instead of dispatching a command that will throw.","Catch InvalidCommandException at the API boundary and map it to a 400/404 with a descriptive body."],"exampleFix":"// before\nawait _commandDispatcher.SendAsync(new DisableMeetingCommentingConfigurationCommand(meetingId));\n\n// after\nvar exists = await _meetingQueries.ConfigurationExistsForMeetingAsync(meetingId);\nif (!exists) return NotFound(\"Commenting configuration not found for meeting.\");\nawait _commandDispatcher.SendAsync(new DisableMeetingCommentingConfigurationCommand(meetingId));","handlingStrategy":"validation","validationCode":"var exists = await _meetingQueries.ConfigurationExistsForMeetingAsync(meetingId);\nif (!exists) return NotFound(\"Commenting configuration not found for meeting.\");\nawait _commandDispatcher.SendAsync(new DisableMeetingCommentingConfigurationCommand(meetingId));","typeGuard":"public static bool IsValidMeetingId(DisableMeetingCommentingConfigurationCommand c) =>\n    c.MeetingId != 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":["Disable the 'disable comments' action in the UI until the configuration is confirmed present.","Run integration tests that assert the configuration is created alongside the meeting.","Never dispatch with an empty Guid; guard at the controller boundary."],"tags":["meetings","commenting-configuration","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"}