{"record":{"id":"e691a71fc71d7a09","repo":"medusajs/medusa","slug":"application-method-max-quantity-is-required-when-a","errorCode":null,"errorMessage":"application_method.max_quantity is required when application_method.allocation is '${allowedAllocationForQuantity.join(\" OR \")}'","messagePattern":"application_method\\.max_quantity is required when application_method\\.allocation is '(.+?)'","errorType":"validation","errorClass":"MedusaError","httpStatus":400,"severity":"error","filePath":"packages/modules/promotion/src/utils/validations/application-method.ts","lineNumber":156,"sourceCode":"  const allAllocationTypes: string[] = Object.values(\n    ApplicationMethodAllocation\n  )\n\n  if (allocation && !allAllocationTypes.includes(allocation)) {\n    throw new MedusaError(\n      MedusaError.Types.INVALID_DATA,\n      `application_method.allocation should be one of ${allAllocationTypes.join(\n        \", \"\n      )}`\n    )\n  }\n\n  if (\n    allocation &&\n    allowedAllocationForQuantity.includes(allocation) &&\n    !isDefined(maxQuantity)\n  ) {\n    throw new MedusaError(\n      MedusaError.Types.INVALID_DATA,\n      `application_method.max_quantity is required when application_method.allocation is '${allowedAllocationForQuantity.join(\n        \" OR \"\n      )}'`\n    )\n  }\n\n  if (\n    allocation === ApplicationMethodAllocation.ONCE &&\n    targetType === ApplicationMethodTargetType.ORDER\n  ) {\n    throw new MedusaError(\n      MedusaError.Types.INVALID_DATA,\n      `application_method.allocation 'once' is not compatible with target_type 'order'`\n    )\n  }\n}\n","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/medusajs/medusa/blob/5e06e544a296b9033f20f71f11c559f81a0e5739/packages/modules/promotion/src/utils/validations/application-method.ts#L138-L174","documentation":"For allocations in allowedAllocationForQuantity (i.e., 'each'), application_method.max_quantity is required. Per-item allocation needs an explicit cap on how many items the adjustment applies to; absence throws INVALID_DATA.","triggerScenarios":"Creating a promotion with allocation 'each' and target_type 'items' but no max_quantity (e.g., an each-allocated percentage discount).","commonSituations":"Assuming max_quantity only matters for buy-get, migrating promotions where the column was nullable, forms not exposing the field for 'each' allocation.","solutions":["Add max_quantity when allocation is 'each' — set it high (e.g., a large number) for effectively unlimited items","Switch to allocation 'across' if a per-item cap is not desired (and then remove max_quantity per the other rule)","Include max_quantity in every seed/import row for each-allocated methods"],"exampleFix":"// before\napplication_method: { type: \"percentage\", value: 10, target_type: \"items\", allocation: \"each\" }\n\n// after\napplication_method: { type: \"percentage\", value: 10, target_type: \"items\", allocation: \"each\", max_quantity: 1000 }","handlingStrategy":"validation","validationCode":"if (allocation === ApplicationMethodAllocation.EACH && !isDefined(maxQuantity)) {\n  maxQuantity = 1000 // sensible unlimited-ish cap\n}","typeGuard":"const eachAllocationHasMaxQuantity = (am: { allocation?: string; max_quantity?: number | null }): boolean => am.allocation !== \"each\" || am.max_quantity !== undefined && am.max_quantity !== null","tryCatchPattern":"try { await createPromotions(...) } catch (e) { if (e.type === MedusaError.Types.INVALID_DATA && /max_quantity is required when/.test(e.message)) { /* add max_quantity and resubmit */ } throw e }","preventionTips":["Remember 'each' allocation requires max_quantity","Default max_quantity high for effectively unlimited","Prefer 'across' when no per-item cap is wanted"],"tags":["promotion","application-method","allocation","required-field","medusa"],"backgroundTag":"missing-required-field","analyzedSha":"5e06e544a296b9033f20f71f11c559f81a0e5739","analyzedAt":"2026-08-27T07:24:39.599Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}