{"record":{"id":"8efb7ed1bba84366","repo":"medusajs/medusa","slug":"rule-value-must-be-a-string-bool-number-value-fo","errorCode":null,"errorMessage":"Rule value must be a string, bool, number value for the selected operator ${rule.operator}","messagePattern":"Rule value must be a string, bool, number value for the selected operator (.+?)","errorType":"validation","errorClass":"MedusaError","httpStatus":400,"severity":"error","filePath":"packages/modules/fulfillment/src/utils/utils.ts","lineNumber":138,"sourceCode":"  if (!availableOperators.includes(rule.operator as RuleOperator)) {\n    throw new MedusaError(\n      MedusaError.Types.INVALID_DATA,\n      `Rule operator ${\n        rule.operator\n      } is not supported. Must be one of ${availableOperators.join(\", \")}`\n    )\n  }\n\n  if (rule.operator === RuleOperator.IN || rule.operator === RuleOperator.NIN) {\n    if (!Array.isArray(rule.value)) {\n      throw new MedusaError(\n        MedusaError.Types.INVALID_DATA,\n        \"Rule value must be an array for in/nin operators\"\n      )\n    }\n  } else {\n    if (Array.isArray(rule.value) || isObject(rule.value)) {\n      throw new MedusaError(\n        MedusaError.Types.INVALID_DATA,\n        `Rule value must be a string, bool, number value for the selected operator ${rule.operator}`\n      )\n    }\n  }\n\n  return true\n}\n\nexport function normalizeRulesValue<T extends Partial<Rule>>(rules: T[]): void {\n  rules.forEach((rule: any) => {\n    /**\n     * If a boolean is provided, then we convert to string\n     */\n    if (rule.value === true || rule.value === false) {\n      rule.value = rule.value === true ? \"true\" : \"false\"\n    }\n","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/medusajs/medusa/blob/5e06e544a296b9033f20f71f11c559f81a0e5739/packages/modules/fulfillment/src/utils/utils.ts#L120-L156","documentation":"For operators other than in/nin, the rule value must be a scalar (string, boolean, or number). Passing an array or object throws INVALID_DATA.","triggerScenarios":"rules: [{ attribute: 'cart_total', operator: 'gt', value: [100] }] or value: { amount: 100 }.","commonSituations":"Reusing an array value from an 'in' rule on a comparison operator; sending nested JSON from a generic form builder.","solutions":["Unwrap scalars: value: 100 not [100]","Switch to in/nin if you genuinely need a list of values"],"exampleFix":"// before\nrules: [{ attribute: 'cart_total', operator: 'gt', value: [100] }]\n// after\nrules: [{ attribute: 'cart_total', operator: 'gt', value: 100 }]","handlingStrategy":"validation","validationCode":"if (!['in','nin'].includes(rule.operator) && (Array.isArray(rule.value) || typeof rule.value === 'object')) throw new TypeError('Scalar value required')","typeGuard":"const isScalarValue = (v: unknown): boolean => ['string','boolean','number'].includes(typeof v)","tryCatchPattern":null,"preventionTips":["Unwrap [x] to x for comparison operators","Reject nested-object values from generic form builders"],"tags":["fulfillment","rules","validation","scalar"],"backgroundTag":"schema-validation-failed","analyzedSha":"5e06e544a296b9033f20f71f11c559f81a0e5739","analyzedAt":"2026-08-27T07:24:39.599Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}