{"record":{"id":"6e2c3027759d93e4","repo":"prestodb/presto","slug":"invalid-decimal-value-stringvalue","errorCode":null,"errorMessage":"Invalid decimal value '{stringValue}'","messagePattern":"Invalid decimal value '(.+?)'","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"presto-common/src/main/java/com/facebook/presto/common/type/Decimals.java","lineNumber":91,"sourceCode":"        return BIG_INTEGER_POWERS_OF_TEN[n];\n    }\n\n    public static DecimalParseResult parse(String stringValue)\n    {\n        return parse(stringValue, false);\n    }\n\n    // visible for testing\n    public static DecimalParseResult parseIncludeLeadingZerosInPrecision(String stringValue)\n    {\n        return parse(stringValue, true);\n    }\n\n    private static DecimalParseResult parse(String stringValue, boolean includeLeadingZerosInPrecision)\n    {\n        Matcher matcher = DECIMAL_PATTERN.matcher(stringValue);\n        if (!matcher.matches()) {\n            throw new IllegalArgumentException(\"Invalid decimal value '\" + stringValue + \"'\");\n        }\n\n        String sign = getMatcherGroup(matcher, 1);\n        if (sign.isEmpty()) {\n            sign = \"+\";\n        }\n        String leadingZeros = getMatcherGroup(matcher, 3);\n        String integralPart = getMatcherGroup(matcher, 4);\n        String fractionalPart = getMatcherGroup(matcher, 6);\n\n        if (leadingZeros.isEmpty() && integralPart.isEmpty() && fractionalPart.isEmpty()) {\n            throw new IllegalArgumentException(\"Invalid decimal value '\" + stringValue + \"'\");\n        }\n\n        int scale = fractionalPart.length();\n        int precision;\n        if (includeLeadingZerosInPrecision) {\n            precision = leadingZeros.length() + integralPart.length() + scale;","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-common/src/main/java/com/facebook/presto/common/type/Decimals.java#L73-L109","documentation":"Decimals.parse first matches the input string against DECIMAL_PATTERN; any string that is not a syntactically valid decimal literal (optional sign, digits, optional fraction) throws IllegalArgumentException 'Invalid decimal value ...'. This is a strict parser used when converting string form to a typed decimal, so malformed input is rejected before any numeric work.","triggerScenarios":"Calling Decimals.parse / parseIncludeLeadingZerosInPrecision with a string that fails DECIMAL_PATTERN: empty string, 'abc', '1.2.3', '1e5', thousands separators like '1,000', trailing signs like '12-', or multiple decimal points.","commonSituations":"User-supplied string literals cast to DECIMAL; CSV/JSON ingestion where a non-numeric placeholder ('N/A', '--') reaches decimal parsing; locale-formatted numbers with commas or spaces.","solutions":["Pre-validate/normalize the string with a regex or BigDecimal.parse before calling Decimals.parse","Scrub ingestion data (map non-numeric sentinels to NULL) before casting to DECIMAL","Parse with new BigDecimal(value) first to normalize scientific notation, then re-serialize to a plain string","Trim whitespace and strip locale grouping separators before parsing"],"exampleFix":"// before\nlong unscaled = Decimals.parse(userInput).getUnscaledValue(); // throws on '1,234.5'\n// after\nString normalized = userInput.trim().replace(\",\", \"\");\nif (!normalized.matches(\"[+-]?\\\\d*(\\\\.\\\\d*)?\")) {\n    normalized = null; // treat as NULL\n}\nDecimalParseResult result = normalized == null ? null : Decimals.parse(normalized);","handlingStrategy":"validation","validationCode":"private static final Pattern SAFE_DECIMAL = Pattern.compile(\"[+-]?\\\\d*(\\\\.\\\\d*)?\");\npublic static boolean isParseableDecimal(String s) {\n    return s != null && SAFE_DECIMAL.matcher(s.trim().replace(\",\", \"\")).matches()\n        && s.matches(\".*\\\\d.*\");\n}","typeGuard":"public static boolean isNumericLiteral(String s) {\n    return s != null && !s.trim().isEmpty() && s.trim().matches(\"[+-]?\\\\d+(\\\\.\\\\d+)?|\\\\.\\\\d+|\\\\d+\\\\.\");\n}","tryCatchPattern":"try {\n    DecimalParseResult r = Decimals.parse(value);\n} catch (IllegalArgumentException e) {\n    // treat as NULL / route to bad-record path\n}","preventionTips":["Strip locale separators and whitespace before parsing","Map non-numeric sentinels ('N/A', '--') to NULL at ingestion","Pre-parse with BigDecimal for scientific-notation inputs"],"tags":["presto","decimal","parsing","input-validation"],"backgroundTag":"invalid-decimal-literal","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}