medusajs/medusa · error · MedusaError

Application Method value should be a percentage number betwe

Error message

Application Method value should be a percentage number between 0 and 100

What it means

validateApplicationMethodAttributes enforces that percentage application methods have a value in (0, 100]. A value <= 0 or > 100 throws INVALID_DATA, blocking promotion create/update (createPromotions_/updatePromotions_).

Source

Thrown at packages/modules/promotion/src/utils/validations/application-method.ts:53

) {
  const applicationMethod = promotion?.application_method || {}
  const buyRulesMinQuantity =
    data.buy_rules_min_quantity || applicationMethod?.buy_rules_min_quantity
  const applyToQuantity =
    data.apply_to_quantity || applicationMethod?.apply_to_quantity
  const targetType = data.target_type || applicationMethod?.target_type
  const type = data.type || applicationMethod?.type
  const applicationMethodType = data.type || applicationMethod?.type
  const value = new BigNumber(data.value ?? applicationMethod.value ?? 0)
  const maxQuantity = data.max_quantity || applicationMethod.max_quantity
  const allocation = data.allocation || applicationMethod.allocation
  const allTargetTypes: string[] = Object.values(ApplicationMethodTargetType)

  if (
    type === ApplicationMethodType.PERCENTAGE &&
    (MathBN.lte(value, 0) || MathBN.gt(value, 100))
  ) {
    throw new MedusaError(
      MedusaError.Types.INVALID_DATA,
      `Application Method value should be a percentage number between 0 and 100`
    )
  }

  if (promotion?.type === PromotionType.BUYGET) {
    if (!isPresent(applyToQuantity)) {
      throw new MedusaError(
        MedusaError.Types.INVALID_DATA,
        `apply_to_quantity is a required field for Promotion type of ${PromotionType.BUYGET}`
      )
    }

    if (!isPresent(buyRulesMinQuantity)) {
      throw new MedusaError(
        MedusaError.Types.INVALID_DATA,
        `buy_rules_min_quantity is a required field for Promotion type of ${PromotionType.BUYGET}`
      )

View on GitHub (pinned to 5e06e544a2)

Solutions

  1. Clamp/validate the percentage to 1–100 in the client form before submission
  2. If a free (100%-off-like) discount is needed, use value 100 exactly — do not exceed it
  3. Sanitize imported data: convert basis points by dividing by 100, treat 0 as invalid and skip

Example fix

// before
await promotionModule.createPromotions({ code: "SUMMER", type: "standard", application_method: { type: "percentage", value: 150, target_type: "items", allocation: "each" } })

// after
await promotionModule.createPromotions({ code: "SUMMER", type: "standard", application_method: { type: "percentage", value: 50, target_type: "items", allocation: "each" } })
Defensive patterns

Strategy: validation

Validate before calling

if (applicationMethod.type === "percentage") {
  const v = Number(applicationMethod.value)
  if (!(v > 0 && v <= 100)) throw new Error("percentage must be in (0, 100]")
}

Type guard

const isValidPercentage = (am: { type?: string; value?: number | string }): boolean => am.type !== "percentage" || (Number(am.value) > 0 && Number(am.value) <= 100)

Try / catch

try { await createPromotions(...) } catch (e) { if (e.type === MedusaError.Types.INVALID_DATA && /percentage number between 0 and 100/.test(e.message)) { /* clamp value and resubmit */ } throw e }

Prevention

When it happens

Trigger: Creating or updating a promotion with application_method.type 'percentage' and value 0, negative, or e.g. 150; also passing value as a decimal string the BigNumber math still evaluates out of range.

Common situations: Forms allowing 0% or >100% discounts, importing legacy promo data with 0 as sentinel for 'no discount', unit confusion (passing basis points 1500 instead of 15%).

Related errors


AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27). Data as JSON: /api/errors/e01140bc8fecea28. Report an issue: GitHub.