{"record":{"id":"35a2e04f3233d5f5","repo":"nocobase/nocobase","slug":"invalid-number-value-value","errorCode":null,"errorMessage":"Invalid number value: \"${value}\"","messagePattern":"Invalid number value: \"(.+?)\"","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/database/src/interfaces/number-interface.ts","lineNumber":41,"sourceCode":"    }\n\n    return value;\n  }\n\n  async toValue(value: any) {\n    if (value === null || value === undefined || typeof value === 'number') {\n      return value;\n    }\n\n    if (!value) {\n      return null;\n    }\n\n    const sanitizedValue = this.sanitizeValue(value);\n    const numberValue = this.parseValue(sanitizedValue);\n\n    if (!this.validate(numberValue)) {\n      throw new Error(`Invalid number value: \"${value}\"`);\n    }\n\n    return numberValue;\n  }\n\n  parseValue(value) {\n    return value;\n  }\n\n  validate(value) {\n    return !isNaN(value);\n  }\n\n  toString(value: number, ctx?: any) {\n    value = super.toString(value, ctx);\n    const step = this.options?.uiSchema?.['x-component-props']?.step;\n    if (value != null && !_.isUndefined(step)) {\n      const s = step.toString();","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/nocobase/nocobase/blob/fa42722fefe44265490dff2c27d79e2882bce4fa/packages/core/database/src/interfaces/number-interface.ts#L23-L59","documentation":"The number interface sanitizes and parses the input, then validates the resulting numeric value; if validation fails (non-finite, NaN, out of expected numeric form), it throws with the original value embedded. This guards number fields against garbage input.","triggerScenarios":"Assigning a value that after sanitizeValue/parseValue still fails validation — e.g. 'abc', '' (empty string), '1,2.3' with mixed separators, objects, or strings with stray characters to a number field via toValue.","commonSituations":"CSV/Excel imports where number columns contain thousand separators, currency symbols ('$1,200'), or text; locale-formatted decimals ('1,5'); form inputs submitting empty strings instead of null.","solutions":["Strip non-numeric characters and normalize the decimal separator before assignment: parseFloat(String(v).replace(/[^0-9.-]/g, '')).","Treat empty strings as null instead of passing them to the field.","Validate payloads at the API boundary with a numeric schema check (Number.isFinite).","Fix import column mapping so the value lands in the correct field type."],"exampleFix":"// before\nawait repo.create({ values: { price: '$1,200.50' } });\n// after\nconst price = parseFloat(String(raw).replace(/[^0-9.\\-]/g, ''));\nif (!Number.isFinite(price)) throw new Error('bad price');\nawait repo.create({ values: { price } });","handlingStrategy":"validation","validationCode":"function toNumberSafe(v) {\n  if (v == null || v === '') return null;\n  const n = typeof v === 'number' ? v : parseFloat(String(v).replace(/[^0-9.\\-]/g, ''));\n  if (!Number.isFinite(n)) throw new Error(`Not a number: ${JSON.stringify(v)}`);\n  return n;\n}","typeGuard":"function isNumericInput(v) {\n  if (typeof v === 'number') return Number.isFinite(v);\n  return typeof v === 'string' && v.trim() !== '' && Number.isFinite(Number(v));\n}","tryCatchPattern":"try {\n  await repo.create({ values: { amount } });\n} catch (e) {\n  if (e.message.startsWith('Invalid number value:')) {\n    console.warn(`Unparsable number: ${e.message}`);\n  } else throw e;\n}","preventionTips":["Strip currency symbols and thousand separators before saving","Normalize locale decimals ('1,5' → 1.5) on import","Convert empty strings to null","Validate number payloads with Number.isFinite at the API boundary"],"tags":["validation","number","parsing"],"backgroundTag":"invalid-number-value","analyzedSha":"fa42722fefe44265490dff2c27d79e2882bce4fa","analyzedAt":"2026-09-01T00:54:31.202Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}