medusajs/medusa · error · MedusaError
invalid_data
invalid_data
Error message
invalidOperatorError
What it means
When upserting price list rules with array values, each rule object must carry an operator that exists in the allowed rule operator set (e.g. 'eq', 'gt', 'lt', 'gte', 'lte', 'in'...). Using an unknown operator throws INVALID_DATA with the shared invalidOperatorError message.
Source
Thrown at packages/modules/pricing/src/services/pricing-module.ts:938
const existingPricesMap = new Map<string, PricingTypes.PriceDTO>()
Array.from(existingPrices ?? []).forEach((price) => {
existingPricesMap.set(hashPrice(price), price)
})
const ruleOperatorsSet = new Set<PricingRuleOperatorValues>(
Object.values(PricingRuleOperator)
)
const validOperatorsList = Array.from(ruleOperatorsSet).join(", ")
const invalidOperatorError = `operator should be one of ${validOperatorsList}`
data?.forEach((price) => {
const cleanRules = price.rules ? removeNullish(price.rules) : {}
const rules = Object.entries(cleanRules).flatMap(([attribute, value]) => {
if (Array.isArray(value)) {
return value.map((customRule) => {
if (!ruleOperatorsSet.has(customRule.operator)) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
invalidOperatorError
)
}
if (typeof customRule.value !== "number") {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`value should be a number`
)
}
return {
attribute,
operator: customRule.operator,
// TODO: we throw above if value is not a number, but the model expect the value to be a string
value: customRule.value.toString(),
}View on GitHub (pinned to 5e06e544a2)
Solutions
- Use only supported operators (eq, ne, gt, gte, lt, lte, in) — check ruleOperatorsSet in the pricing module for the exact list
- Fix typos such as 'equals' → 'eq' or '>=' → 'gte'
- If building rules dynamically, validate the operator against an allowlist before calling the API
Example fix
// before
rules: { region_id: [{ operator: 'equals', value: 'reg_123' }] }
// after
rules: { region_id: [{ operator: 'eq', value: 'reg_123' }] } Defensive patterns
Strategy: validation
Validate before calling
const ALLOWED_OPERATORS = ['eq','ne','gt','gte','lt','lte','in'] as const
const normalizeOperator = (op: string) =>
({ equals: 'eq', '=': 'eq', '>=': 'gte', '<=': 'lte' } as Record<string,string>)[op] ?? op
const rules = Object.fromEntries(
Object.entries(rawRules).map(([k, v]) => [
k,
Array.isArray(v)
? v.map((r) => ({ ...r, operator: normalizeOperator(r.operator) }))
: v,
])
)
// verify before calling
for (const v of Object.values(rules)) {
if (Array.isArray(v)) v.forEach((r) => {
if (!ALLOWED_OPERATORS.includes(r.operator)) throw new Error(`Bad operator: ${r.operator}`)
})
} Type guard
const isRuleOperator = (op: unknown): op is 'eq'|'ne'|'gt'|'gte'|'lt'|'lte'|'in' => typeof op === 'string' && ['eq','ne','gt','gte','lt','lte','in'].includes(op)
Prevention
- Centralize rule-building in one helper with an operator allowlist
- Add a unit test enumerating supported operators
When it happens
Trigger: Calling updatePriceListRules / addPriceListRules-style APIs (upserting prices with rules) where a rule value is an array of { operator, value } objects and operator is misspelled or unsupported, e.g. 'equals' instead of 'eq'.
Common situations: Porting code from an older Medusa version where rules were plain key-value maps, guessing operator names, or string typos in dynamic rule building.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Invalid rule attribute - ${ruleAttributeId}
- Rule must have an attribute, an operator and a value
- Rule operator ${rule.operator} is not supported. Must be one
- Rule value must be an array for in/nin operators
- Rule value must be a string, bool, number value for the sele
AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27).
Data as JSON: /api/errors/e1841fa6cce2c9c6.
Report an issue: GitHub.