{"record":{"id":"851445b9e27f7f1a","repo":"kgrzybek/modular-monolith-with-ddd","slug":"pricelist-item-for-changing-must-exist","errorCode":null,"errorMessage":"Pricelist item for changing must exist.","messagePattern":"Pricelist item for changing must exist\\.","errorType":"validation","errorClass":"InvalidCommandException","httpStatus":400,"severity":"error","filePath":"src/Modules/Payments/Application/PriceListItems/ChangePriceListItemAttributes/ChangePriceListItemAttributesCommandHandler.cs","lineNumber":24,"sourceCode":"\r\nnamespace CompanyName.MyMeetings.Modules.Payments.Application.PriceListItems.ChangePriceListItemAttributes\r\n{\r\n    internal class ChangePriceListItemAttributesCommandHandler : ICommandHandler<ChangePriceListItemAttributesCommand>\r\n    {\r\n        private readonly IAggregateStore _aggregateStore;\r\n\r\n        public ChangePriceListItemAttributesCommandHandler(IAggregateStore aggregateStore)\r\n        {\r\n            _aggregateStore = aggregateStore;\r\n        }\r\n\r\n        public async Task Handle(ChangePriceListItemAttributesCommand command, CancellationToken cancellationToken)\r\n        {\r\n            var priceListItem = await _aggregateStore.Load(new PriceListItemId(command.PriceListItemId));\r\n\r\n            if (priceListItem == null)\r\n            {\r\n                throw new InvalidCommandException([\"Pricelist item for changing must exist.\"]);\r\n            }\r\n\r\n            priceListItem.ChangeAttributes(\r\n                command.CountryCode,\r\n                SubscriptionPeriod.Of(command.SubscriptionPeriodCode),\r\n                PriceListItemCategory.Of(command.CategoryCode),\r\n                MoneyValue.Of(command.PriceValue, command.PriceCurrency));\r\n\r\n            _aggregateStore.AppendChanges(priceListItem);\r\n        }\r\n    }\r\n}","sourceCodeStart":6,"sourceCodeEnd":36,"githubUrl":"https://github.com/kgrzybek/modular-monolith-with-ddd/blob/91c8ef24b4cb6ef558c95d8267fa07d68c7059f8/src/Modules/Payments/Application/PriceListItems/ChangePriceListItemAttributes/ChangePriceListItemAttributesCommandHandler.cs#L6-L36","documentation":"Thrown by ChangePriceListItemAttributesCommandHandler when _aggregateStore.Load returns null for the PriceListItemId. Changing attributes requires the aggregate to exist; a missing item aborts with InvalidCommandException (HTTP 400) before applying ChangeAttributes.","triggerScenarios":"Dispatching ChangePriceListItemAttributesCommand for a non-existent id: wrong Guid, item deleted, wrong tenant, or stream not found.","commonSituations":"Editing a price list row in an admin grid that has since been deactivated/removed; cross-environment id copy; bulk import referencing stale ids.","solutions":["Confirm the item exists and belongs to the right country/period scope.","Validate the command's CountryCode/SubscriptionPeriodCode/CategoryCode values are in the allowed catalogs (these feed MoneyValue/SubscriptionPeriod.Of which can also throw).","Pre-check existence in the controller and return 404.","Map InvalidCommandException to 400/404 at the API boundary."],"exampleFix":"// before\nawait _commandDispatcher.SendAsync(new ChangePriceListItemAttributesCommand(itemId, countryCode, periodCode, categoryCode, value, currency));\n\n// after\nvar item = await _priceListQueries.GetItemAsync(itemId);\nif (item is null) return NotFound(\"Price list item not found.\");\nawait _commandDispatcher.SendAsync(new ChangePriceListItemAttributesCommand(itemId, countryCode, periodCode, categoryCode, value, currency));","handlingStrategy":"validation","validationCode":"var item = await _priceListQueries.GetItemAsync(itemId);\nif (item is null) return NotFound(\"Price list item not found.\");\nawait _commandDispatcher.SendAsync(new ChangePriceListItemAttributesCommand(itemId, countryCode, periodCode, categoryCode, value, currency));","typeGuard":"public static bool IsValidChangeCommand(ChangePriceListItemAttributesCommand c) =>\n    c.PriceListItemId != Guid.Empty\n    && !string.IsNullOrWhiteSpace(c.CountryCode)\n    && c.Value >= 0\n    && !string.IsNullOrWhiteSpace(c.Currency);","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":["Confirm item existence and correct country/period scope before editing.","Pre-validate enum codes against the allowed catalogs before dispatch.","Reject empty Guid and negative money client-side."],"tags":["payments","price-list","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"}