{"record":{"id":"f12ee55a585daced","repo":"Automattic/mongoose","slug":"cast-to-decimal128-failed-for-value-value-ty","errorCode":null,"errorMessage":"Cast to Decimal128 failed for value \"${value}\" (type ${valueType}) at path \"${path}\"","messagePattern":"Cast to Decimal128 failed for value \"(.+?)\" \\(type (.+?)\\) at path \"(.+?)\"","errorType":"exception","errorClass":"CastError","httpStatus":null,"severity":"error","filePath":"lib/schema/decimal128.js","lineNumber":206,"sourceCode":"      return value;\n    }\n\n    return this._castRef(value, doc, init, options);\n  }\n\n  let castDecimal128;\n  if (typeof this._castFunction === 'function') {\n    castDecimal128 = this._castFunction;\n  } else if (typeof this.constructor.cast === 'function') {\n    castDecimal128 = this.constructor.cast();\n  } else {\n    castDecimal128 = SchemaDecimal128.cast();\n  }\n\n  try {\n    return castDecimal128(value);\n  } catch (error) {\n    throw new CastError('Decimal128', value, this.path, error, this);\n  }\n};\n\n/*!\n * ignore\n */\n\nfunction handleSingle(val) {\n  return this.cast(val);\n}\n\nconst $conditionalHandlers = {\n  ...SchemaType.prototype.$conditionalHandlers,\n  $gt: handleSingle,\n  $gte: handleSingle,\n  $lt: handleSingle,\n  $lte: handleSingle\n};","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/schema/decimal128.js#L188-L224","documentation":"SchemaDecimal128.cast converts failures of the Decimal128 caster (lib/cast/decimal128.js) into this CastError. The caster accepts Decimal128 instances, strings via Decimal128.fromString (strict decimal-literal parsing), numbers, `{ $numberDecimal: '...' }` Extended JSON, and 16-byte Buffer/Uint8Array values. It rejects booleans, plain objects, arrays, and strings Decimal128.fromString cannot parse ('abc', '1,5', '$10.00').","triggerScenarios":"`doc.price = 'abc'`, `doc.price = { value: '1.5' }` (object without $numberDecimal), `doc.price = '1.234,56'` (comma decimal), `doc.price = '$10.00'` (currency symbol), or passing an array. Query side: `{ price: { $gt: 'free' } }` via handleSingle.","commonSituations":"Money fields fed unsanitized user input; locale-formatted numbers from European formats; currency strings from scraping or spreadsheets; JSON where the decimal arrives inside a wrapper object from another serializer.","solutions":["Sanitize to a plain decimal string before assigning: strip currency symbols/thousands separators, then validate against `/^[+-]?\\d+(\\.\\d+)?$/`","Assign `mongoose.Types.Decimal128.fromString(cleanValue)` yourself inside a try/catch at the boundary","Pass numbers directly (`doc.price = 10.5`) when precision loss is acceptable","If input formats vary wildly, register a custom caster with `mongoose.Schema.Types.Decimal128.cast(...)`"],"exampleFix":"// before\nproduct.price = req.body.price; // '$1,234.56'\n\n// after\nconst clean = String(req.body.price).replace(/[$,]/g, '');\nif (!/^[+-]?\\d+(\\.\\d+)?$/.test(clean)) throw new ValidationError('bad price');\nproduct.price = mongoose.Types.Decimal128.fromString(clean);","handlingStrategy":"validation","validationCode":"const DECIMAL_RE = /^[+-]?\\d+(\\.\\d+)?$/;\nfunction toDecimal128(v) {\n  if (v == null) return v;\n  const s = typeof v === 'object' && typeof v.$numberDecimal === 'string' ? v.$numberDecimal : String(v);\n  const clean = s.replace(/[$,\\s]/g, '');\n  if (!DECIMAL_RE.test(clean)) throw new Error(`not a decimal: ${s}`);\n  return mongoose.Types.Decimal128.fromString(clean);\n}","typeGuard":"function isDecimalLike(v) {\n  if (v == null || typeof v === 'number') return true;\n  const s = typeof v === 'string' ? v : (v && v.$numberDecimal);\n  return typeof s === 'string' && /^[+-]?\\d+(\\.\\d+)?$/.test(s.replace(/[$,]/g, ''));\n}","tryCatchPattern":"try { doc.price = value; } catch (err) { if (err.name === 'CastError' && err.kind === 'Decimal128') { return badRequest('price must be a decimal number'); } throw err; }","preventionTips":["Sanitize currency/locale strings before they reach models","Validate decimal fields with a strict regex in your request schema","Assign Decimal128.fromString() yourself at the boundary to control the error"],"tags":["mongoose","decimal128","cast","validation","money"],"backgroundTag":"mongoose-cast-error","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}