{"record":{"id":"8a686b647bd8e506","repo":"apache/flink","slug":"invalid-character","errorCode":null,"errorMessage":"Invalid character.","messagePattern":"Invalid character\\.","errorType":"exception","errorClass":"NumberFormatException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/types/parser/ByteParser.java","lineNumber":138,"sourceCode":"        if (bytes[startPos] == delimiter) {\n            throw new NumberFormatException(\"Empty field.\");\n        }\n\n        if (bytes[startPos] == '-') {\n            neg = true;\n            startPos++;\n            length--;\n            if (length == 0 || bytes[startPos] == delimiter) {\n                throw new NumberFormatException(\"Orphaned minus sign.\");\n            }\n        }\n\n        for (; length > 0; startPos++, length--) {\n            if (bytes[startPos] == delimiter) {\n                return (byte) (neg ? -val : val);\n            }\n            if (bytes[startPos] < 48 || bytes[startPos] > 57) {\n                throw new NumberFormatException(\"Invalid character.\");\n            }\n            val *= 10;\n            val += bytes[startPos] - 48;\n\n            if (val > Byte.MAX_VALUE && (!neg || val > -Byte.MIN_VALUE)) {\n                throw new NumberFormatException(\"Value overflow/underflow\");\n            }\n        }\n        return (byte) (neg ? -val : val);\n    }\n}\n","sourceCodeStart":120,"sourceCodeEnd":150,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/types/parser/ByteParser.java#L120-L150","documentation":"Thrown by ByteParser.parseField during the digit loop when a byte inside the numeric field is outside '0'..'9'. The parser is strict: no thousands separators, no '+', no decimal point, no whitespace — only ASCII digits (checked via byte range 48-57) after an optional leading '-' are accepted for byte fields.","triggerScenarios":"Calling ByteParser.parseField with fields like \"1,000\", \"12 \", \"0x1F\", \"+5\", or \"3.0\" — any non-digit byte before the delimiter triggers the rejection at ByteParser.java:140.","commonSituations":"Locale-formatted numbers with grouping separators from spreadsheets; float values fed into a byte/int column; hex or signed-plus notation; schema drift where a byte column starts receiving formatted strings.","solutions":["Emit plain unformatted integers (no separators, no plus sign) for byte columns at the producer.","If the value may be fractional or formatted, parse it as double/BigDecimal first and range-check before narrowing to byte.","Pre-scan the field for non-digit bytes and route bad records to a dead-letter/side output."],"exampleFix":"// before\nbyte v = ByteParser.parseField(bytes, start, len, '|'); // fails on \"1,000\"\n\n// after\nString field = new String(bytes, start, len, StandardCharsets.UTF_8).replace(\",\", \"\");\nbyte v = Byte.valueOf(field.trim());","handlingStrategy":"validation","validationCode":"for (int i = 0; i < len; i++) {\n    byte b = bytes[start + i];\n    if (b == (byte) delimiter) break;\n    if (b < 48 || b > 57) throw new IllegalArgumentException(\"Non-digit byte in byte field: \" + (char) b);\n}","typeGuard":null,"tryCatchPattern":"try {\n    byte v = ByteParser.parseField(bytes, start, len, delim);\n} catch (NumberFormatException e) {\n    String raw = new String(bytes, start, len, StandardCharsets.UTF_8);\n    byte v = Byte.parseByte(raw.replace(\",\", \"\").trim()); // fallback for formatted input\n}","preventionTips":["Emit unformatted integers (no separators, '+', or '.') for byte columns.","Pre-validate fields are digit-only before strict parsing.","Route non-conforming records to a reprocessing path instead of crashing the pipeline."],"tags":["parser","byte","invalid-character","csv","flink-core"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}