{"record":{"id":"93e715f40aa88919","repo":"github/copilot-sdk","slug":"expected-digit-in-number-part-at-position-pos","errorCode":null,"errorMessage":"Expected digit in number <part> at position <pos>","messagePattern":"Expected digit in number <part> at position <pos>","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"java/sdk/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java","lineNumber":1140,"sourceCode":"                if (pos < input.length() && (input.charAt(pos) == '+' || input.charAt(pos) == '-')) {\n                    pos++;\n                }\n                requireDigit(\"exponent\");\n                consumeDigits();\n            }\n            String number = input.substring(start, pos);\n            try {\n                new java.math.BigDecimal(number);\n            } catch (NumberFormatException e) {\n                throw new IllegalArgumentException(\"Number cannot be represented at position \" + start + \": \" + number,\n                        e);\n            }\n            return \"new java.math.BigDecimal(\\\"\" + number + \"\\\")\";\n        }\n\n        private void requireDigit(String part) {\n            if (pos >= input.length() || !isAsciiDigit(input.charAt(pos))) {\n                throw new IllegalArgumentException(\"Expected digit in number \" + part + \" at position \" + pos);\n            }\n        }\n\n        private void consumeDigits() {\n            while (pos < input.length() && isAsciiDigit(input.charAt(pos))) {\n                pos++;\n            }\n        }\n\n        private boolean isAsciiDigit(char c) {\n            return c >= '0' && c <= '9';\n        }\n\n        private boolean isDigitOneToNine(char c) {\n            return c >= '1' && c <= '9';\n        }\n\n        private void skipWhitespace() {","sourceCodeStart":1122,"sourceCodeEnd":1158,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/java/sdk/src/main/java/com/github/copilot/tool/CopilotToolProcessor.java#L1122-L1158","documentation":"The JSON number parser in CopilotToolProcessor calls requireDigit(part) after seeing '.' or 'e'/'E' to demand at least one digit in the fraction or exponent part. If the input ends or a non-digit follows, it throws this IllegalArgumentException naming which part ('fraction' or 'exponent') was missing a digit. JSON forbids literals like 1. or 1e.","triggerScenarios":"Arguments containing number literals with a dangling decimal point (\"1.\") or dangling exponent marker (\"1e\", \"1e-\") — the character after the marker is missing or not a digit.","commonSituations":"Truncated LLM output (stream ended mid-number), copy-paste of numbers formatted for humans (e.g. \"5.\" at end of a sentence), template generation bugs.","solutions":["Complete the number: change 1. to 1.0 and 1e to 1e0 (or drop the marker).","Ensure the JSON source is complete before parsing (check stream/string termination).","Catch IllegalArgumentException and use the pos/part detail to report precisely where the number is truncated."],"exampleFix":"// before\n{\"threshold\": 0.}\n// after\n{\"threshold\": 0.0}","handlingStrategy":"validation","validationCode":"static boolean hasCompleteNumbers(String json) {\n    return json.matches(\".*\\\\d+(\\\\.\\\\d+)?([eE][+-]?\\\\d+)?.*\")\n        && !java.util.regex.Pattern.compile(\"\\\\d\\\\.([^\\\\d]|$)|\\\\d[eE]([^\\\\d]|$)\").matcher(json).find();\n}","typeGuard":"static boolean completeNumberAt(String s, int i) {\n    // after '.' or 'e'/'E' there must be at least one digit\n    return i + 1 < s.length() && Character.isDigit(s.charAt(i + 1));\n}","tryCatchPattern":"try {\n    processor.parse(args);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Expected digit in number\")) {\n        // input likely truncated — request the remainder before retrying\n    }\n    throw e;\n}","preventionTips":["Only parse JSON after the producing stream has fully terminated.","Reject human-formatted numbers like \"5.\" during argument generation.","Validate with a reference JSON parser before invoking the tool processor."],"tags":["json","parsing","number-format","truncated-input"],"backgroundTag":"json-parse-error","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}