medusajs/medusa · error · MedusaError
Cannot add promotions to campaign where currency_code don't
Error message
Cannot add promotions to campaign where currency_code don't match.
What it means
Thrown when adding promotions to a campaign whose budget type is SPEND: every promotion's application_method.currency_code must match the campaign budget's currency_code. A mismatch (including a promotion with a null currency_code against a budget with one, or vice versa) rejects the whole batch with INVALID_DATA.
Source
Thrown at packages/modules/promotion/src/services/promotion-module.ts:2045
if (diff.length > 0) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`Cannot add promotions (${diff.join(
","
)}) to campaign. These promotions are either already part of a campaign or not found.`
)
}
const promotionsWithInvalidCurrency = promotionsToAdd.filter(
(promotion) =>
campaign.budget?.type === CampaignBudgetType.SPEND &&
promotion.application_method?.currency_code !==
campaign?.budget?.currency_code
)
if (promotionsWithInvalidCurrency.length > 0) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Cannot add promotions to campaign where currency_code don't match.`
)
}
await this.promotionService_.update(
promotionsToAdd.map((promotion) => ({
id: promotion.id,
campaign_id: campaign.id,
})),
sharedContext
)
return promotionsToAdd.map((promo) => promo.id)
}
@InjectManager()
@EmitEvents()View on GitHub (pinned to 5e06e544a2)
Solutions
- Match the campaign budget currency to the promotions' currency (update campaign budget currency_code or the application methods' currency_code)
- Only attach promotions whose application_method.currency_code equals the campaign budget currency; group promotions into per-currency campaigns
- If promotions are percentage-based and have no currency, give the application method the campaign's currency or use a usage-type budget instead of spend
Example fix
// before
await campaignModule.addPromotionsToCampaign(usdCampaignId, {
promo_ids: [eurPromoId],
})
// after
const promos = await promotionModule.listPromotions({ id: promoIds }, { relations: ["application_method"] })
const matching = promos
.filter((p) => p.application_method?.currency_code === campaignBudgetCurrency)
.map((p) => p.id)
await campaignModule.addPromotionsToCampaign(usdCampaignId, { promo_ids: matching }) Defensive patterns
Strategy: validation
Validate before calling
const budgetCurrency = campaign.budget?.type === "spend" ? campaign.budget.currency_code : null const eligible = promotions .filter((p) => !budgetCurrency || p.application_method?.currency_code === budgetCurrency) .map((p) => p.id)
Type guard
const matchesCampaignCurrency = (promo: PromotionDTO, campaign: CampaignDTO): boolean => campaign.budget?.type !== "spend" || promo.application_method?.currency_code === campaign.budget?.currency_code
Try / catch
try { await addPromotionsToCampaign(...) } catch (e) { if (e.type === MedusaError.Types.INVALID_DATA && /currency_code/.test(e.message)) { /* split promotions by currency into separate campaigns */ } throw e } Prevention
- Create one campaign per currency
- Set currency_code on application methods explicitly at creation
- Validate budget currency before batch-adding promotions
When it happens
Trigger: Calling addPromotionsToCampaign where campaign.budget.type === 'spend' and one or more promotions have application_method.currency_code different from campaign.budget.currency_code — e.g., a USD fixed promotion added to an EUR-budget campaign, or a percentage promotion (no currency) added to a currency-budgeted campaign.
Common situations: Multi-region stores mixing currencies, creating campaigns before deciding budget currency, promotions created without currency_code (percentage type) being attached to spend-budget campaigns, default currency assumptions in seed scripts.
Related errors
- Cannot add promotions (${diff.join(",")}) to campaign. These
- Promotions with ids (${diff.join(",")}) not found.
- "${contextKey}" should be present as an array in the context
- Application Method value should be a percentage number betwe
- apply_to_quantity is a required field for Promotion type of
AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27).
Data as JSON: /api/errors/8eb27212a1b5fad7.
Report an issue: GitHub.