{"id":"39fe524fce315dbd","repo":"sequelize/sequelize","slug":"the-this-getdatatypeid-datatype-requires-that","errorCode":null,"errorMessage":"The ${this.getDataTypeId()} DataType requires that the \"precision\" option be specified if the \"scale\" option is specified.","messagePattern":"The (.+?) DataType requires that the \"precision\" option be specified if the \"scale\" option is specified\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/abstract-dialect/data-types.ts","lineNumber":1031,"sourceCode":"    ...args:\n      | []\n      | [precision: number]\n      | [precision: number, scale: number]\n      | [options: DecimalNumberOptions]\n  );\n\n  constructor(precisionOrOptions?: number | DecimalNumberOptions, scale?: number) {\n    if (isObject(precisionOrOptions)) {\n      super(precisionOrOptions);\n    } else {\n      super({});\n\n      this.options.precision = precisionOrOptions;\n      this.options.scale = scale;\n    }\n\n    if (this.options.scale != null && this.options.precision == null) {\n      throw new Error(\n        `The ${this.getDataTypeId()} DataType requires that the \"precision\" option be specified if the \"scale\" option is specified.`,\n      );\n    }\n\n    if (this.options.scale == null && this.options.precision != null) {\n      throw new Error(\n        `The ${this.getDataTypeId()} DataType requires that the \"scale\" option be specified if the \"precision\" option is specified.`,\n      );\n    }\n  }\n\n  validate(value: any): asserts value is AcceptedNumber {\n    if (Number.isNaN(value)) {\n      const typeId = this.getDataTypeId();\n      const dialect = this._getDialect();\n\n      // @ts-expect-error -- 'typeId' is string, but only some dataTypes are objects\n      if (dialect.supports.dataTypes[typeId]?.NaN) {","sourceCodeStart":1013,"sourceCodeEnd":1049,"githubUrl":"https://github.com/sequelize/sequelize/blob/7e1deec499d5afbb8d1877c2f4d545cead1214ec/packages/core/src/abstract-dialect/data-types.ts#L1013-L1049","documentation":"BaseDecimalNumberDataType (data-types.ts:1020) enforces that precision and scale are either both set or both unset. The constructor throws when scale != null && precision == null because SQL DECIMAL(p,s) semantics are undefined when only scale is given (you cannot have digits after the decimal point without first defining total digits). This applies to DECIMAL and any decimal-based number type.","triggerScenarios":"Calling DataTypes.DECIMAL(undefined, 2), new DECIMAL({ scale: 4 }), or BaseDecimalNumberDataType with only the scale option set.","commonSituations":"Mistakenly thinking scale alone means '2 decimal places'; migrating a schema doc that only listed decimal places; refactoring options objects and dropping the precision field.","solutions":["Provide both: DataTypes.DECIMAL(10, 2) or { precision: 10, scale: 2 }.","Provide neither to get an unconstrained DECIMAL (only where the dialect supports it, see error 24).","Re-check that your options object includes both precision and scale keys."],"exampleFix":"// before\namount: { type: DataTypes.DECIMAL({ scale: 2 }) }\n\n// after\namount: { type: DataTypes.DECIMAL({ precision: 10, scale: 2 }) }","handlingStrategy":"validation","validationCode":"function decimalType(p, s) {\n  if ((s != null) && (p == null)) throw new Error('precision required when scale is set');\n  return DataTypes.DECIMAL(p, s);\n}","typeGuard":"function hasBalancedPrecisionScale(o = {}) {\n  const { precision, scale } = o;\n  return (precision == null) === (scale == null);\n}","tryCatchPattern":null,"preventionTips":["Always specify DECIMAL as either (p, s) or () — never a single dimension.","Centralize DECIMAL column definitions so the pair is never split.","Lint for DataTypes.DECIMAL( followed by a single argument."],"tags":["data-types","decimal","precision","scale","validation"],"analyzedSha":"7e1deec499d5afbb8d1877c2f4d545cead1214ec","analyzedAt":"2026-08-03T18:58:44.549Z","schemaVersion":2}