medusajs/medusa · error · MedusaError
Cannot add promotions (${diff.join(",")}) to campaign. These
Error message
Cannot add promotions (${diff.join(",")}) to campaign. These promotions are either already part of a campaign or not found. What it means
Thrown by PromotionModuleService when adding promotions to a campaign: the ids supplied in promotionsToAdd contain at least one id that is not present in the promotionIds resolved from the module (i.e., the promotion does not exist or is not eligible). The diff between requested ids and found ids is non-empty, so the entire operation is rejected with NOT_FOUND.
Source
Thrown at packages/modules/promotion/src/services/promotion-module.ts:2029
data: PromotionTypes.AddPromotionsToCampaignDTO,
@MedusaContext() sharedContext: Context = {}
) {
const { id, promotion_ids: promotionIds = [] } = data
const campaign = await this.campaignService_.retrieve(id, {}, sharedContext)
const promotionsToAdd = await this.promotionService_.list(
{ id: promotionIds, campaign_id: null },
{ relations: ["application_method"] },
sharedContext
)
const diff = arrayDifference(
promotionsToAdd.map((p) => p.id),
promotionIds
)
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.`View on GitHub (pinned to 5e06e544a2)
Solutions
- Verify each promotion id exists via promotionModule.listPromotions({ id: [...] }) before calling addPromotionsToCampaign
- Detach the promotion from its existing campaign first (removePromotionsFromCampaign on the old campaign) if reassignment is intended
- Remove non-existent ids from the payload and retry with only valid ids
- Check for environment mismatch — ids generated in one database will not exist in another
Example fix
// before
await campaignModule.addPromotionsToCampaign(campaignId, {
promo_ids: ["promo_123", "promo_deleted"],
})
// after
const existing = await promotionModule.listPromotions({ id: promoIds })
const validIds = existing.map((p) => p.id)
await campaignModule.addPromotionsToCampaign(campaignId, {
promo_ids: validIds,
}) Defensive patterns
Strategy: validation
Validate before calling
const existing = await promotionModule.listPromotions({ id: promoIds })
const existingIds = new Set(existing.map((p) => p.id))
const validIds = promoIds.filter((id) => existingIds.has(id))
if (validIds.length !== promoIds.length) {
// skip/report unknown ids instead of failing the whole call
} Type guard
const isValidPromotionId = (id: string, existing: Set<string>): boolean => existing.has(id)
Try / catch
try { await addPromotionsToCampaign(...) } catch (e) { if (e instanceof MedusaError && e.type === MedusaError.Types.NOT_FOUND) { /* refresh promo list and retry with valid ids */ } throw e } Prevention
- Fetch fresh promotion ids right before attaching to a campaign
- Never persist promotion ids across environments
- Detach from the previous campaign before reassigning
When it happens
Trigger: Calling addPromotionsToCampaign (or the admin POST /admin/campaigns/:id/promotions route) with promotion ids that were deleted, mis-typed, belong to another scope, or are already assigned to a different campaign so they are filtered out of promotionIds.
Common situations: Stale promotion ids cached in the client/UI, copy-pasting ids between environments (dev/staging/prod), re-adding promotions that were already attached to another campaign, race where the promotion was deleted after the UI loaded the list.
Related errors
- Promotions with ids (${diff.join(",")}) not found.
- Cannot add promotions to campaign where currency_code don't
- Promotion code "${missingPromoCodes[0]}" not found / Promoti
- "items" should be present as an array in the context to comp
- "${contextKey}" should be present as an array in the context
AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27).
Data as JSON: /api/errors/b0bbd03f8b8427d6.
Report an issue: GitHub.