kgrzybek/modular-monolith-with-ddd · error · InvalidCommandException
Pricelist item for changing must exist.
Error message
Pricelist item for changing must exist.
What it means
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.
Source
Thrown at src/Modules/Payments/Application/PriceListItems/ChangePriceListItemAttributes/ChangePriceListItemAttributesCommandHandler.cs:24
namespace CompanyName.MyMeetings.Modules.Payments.Application.PriceListItems.ChangePriceListItemAttributes
{
internal class ChangePriceListItemAttributesCommandHandler : ICommandHandler<ChangePriceListItemAttributesCommand>
{
private readonly IAggregateStore _aggregateStore;
public ChangePriceListItemAttributesCommandHandler(IAggregateStore aggregateStore)
{
_aggregateStore = aggregateStore;
}
public async Task Handle(ChangePriceListItemAttributesCommand command, CancellationToken cancellationToken)
{
var priceListItem = await _aggregateStore.Load(new PriceListItemId(command.PriceListItemId));
if (priceListItem == null)
{
throw new InvalidCommandException(["Pricelist item for changing must exist."]);
}
priceListItem.ChangeAttributes(
command.CountryCode,
SubscriptionPeriod.Of(command.SubscriptionPeriodCode),
PriceListItemCategory.Of(command.CategoryCode),
MoneyValue.Of(command.PriceValue, command.PriceCurrency));
_aggregateStore.AppendChanges(priceListItem);
}
}
}View on GitHub (pinned to 91c8ef24b4)
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.
Example fix
// before
await _commandDispatcher.SendAsync(new ChangePriceListItemAttributesCommand(itemId, countryCode, periodCode, categoryCode, value, currency));
// after
var item = await _priceListQueries.GetItemAsync(itemId);
if (item is null) return NotFound("Price list item not found.");
await _commandDispatcher.SendAsync(new ChangePriceListItemAttributesCommand(itemId, countryCode, periodCode, categoryCode, value, currency)); Defensive patterns
Strategy: validation
Validate before calling
var item = await _priceListQueries.GetItemAsync(itemId);
if (item is null) return NotFound("Price list item not found.");
await _commandDispatcher.SendAsync(new ChangePriceListItemAttributesCommand(itemId, countryCode, periodCode, categoryCode, value, currency)); Type guard
public static bool IsValidChangeCommand(ChangePriceListItemAttributesCommand c) =>
c.PriceListItemId != Guid.Empty
&& !string.IsNullOrWhiteSpace(c.CountryCode)
&& c.Value >= 0
&& !string.IsNullOrWhiteSpace(c.Currency); 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
- 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.
When it happens
Trigger: Dispatching ChangePriceListItemAttributesCommand for a non-existent id: wrong Guid, item deleted, wrong tenant, or stream not found.
Common situations: Editing a price list row in an admin grid that has since been deactivated/removed; cross-environment id copy; bulk import referencing stale ids.
Related errors
- Pricelist item for activation must exist.
- Pricelist item for deactivation must exist.
- Subscription for renewal must exist.
- Meeting commenting configuration for disabling commenting mu
- Meeting commenting configuration for enabling commenting mus
AI-assisted analysis of kgrzybek/modular-monolith-with-ddd@91c8ef24b4 (2026-08-13).
Data as JSON: /api/errors/851445b9e27f7f1a.
Report an issue: GitHub.