apache/kafka · error · NumberFormatException

${about}: failed to parse number: ${cause}

Error message

${about}: failed to parse number: ${cause}

What it means

Thrown by MessageUtil.jsonNodeToInt when asText() of a non-int, non-textual node yields a string that does not parse as a base-10 integer. Because textual JSON values are rejected at line 118, this fires for other node kinds whose asText() is not integral — most commonly DoubleNode ('3.5'), BooleanNode ('true'), NullNode ('null'), or array/object nodes (whose asText() is empty).

Source

Thrown at clients/src/main/java/org/apache/kafka/common/protocol/MessageUtil.java:133

            return node.asInt();
        }
        if (node.isTextual()) {
            throw new NumberFormatException(about + ": expected an integer or " +
                "string type, but got " + node.getNodeType());
        }
        String text = node.asText();
        if (text.startsWith("0x")) {
            try {
                return Integer.parseInt(text.substring(2), 16);
            } catch (NumberFormatException e) {
                throw new NumberFormatException(about + ": failed to " +
                    "parse hexadecimal number: " + e.getMessage());
            }
        } else {
            try {
                return Integer.parseInt(text);
            } catch (NumberFormatException e) {
                throw new NumberFormatException(about + ": failed to " +
                    "parse number: " + e.getMessage());
            }
        }
    }

    public static long jsonNodeToLong(JsonNode node, String about) {
        if (node.isLong()) {
            return node.asLong();
        }
        if (node.isTextual()) {
            throw new NumberFormatException(about + ": expected an integer or " +
                "string type, but got " + node.getNodeType());
        }
        String text = node.asText();
        if (text.startsWith("0x")) {
            try {
                return Long.parseLong(text.substring(2), 16);
            } catch (NumberFormatException e) {

View on GitHub (pinned to c31c9215e1)

Solutions

  1. Inspect the 'about' prefix and the embedded e.getMessage() to identify both the field and the exact token Jackson emitted via asText().
  2. Change the JSON value to an integer literal of the correct magnitude.
  3. If the source data is genuinely fractional/null/boolean, normalize it upstream (round, default, project) before serializing into the protocol message.
  4. Validate the JSON with the generated Message'schema before submission.

Example fix

// before
{"partition_count": 3.0}
// after
{"partition_count": 3}
Defensive patterns

Strategy: validation

Validate before calling

String t = node.asText();
try { Integer.parseInt(t); } catch (NumberFormatException ex) { throw new IllegalArgumentException("unparseable int: " + t, ex); }

Type guard

node != null && node.isInt() || (node.isTextual() && node.asText().matches("-?\d{1,10}") && { try { Integer.parseInt(node.asText()); true } catch { false } })

Try / catch

try { int i = MessageUtil.jsonNodeToInt(node, about); }
catch (NumberFormatException e) { /* non-numeric string in int field; quarantine record */ }

Prevention

When it happens

Trigger: A JSON value such as 3.5, true, null, [] or {} is supplied where a int32 field is expected. node.isInt()==false, node.isTextual()==false, asText() returns '3.5'/'true'/'null'/'' and Integer.parseInt throws — line 133 wraps it as NumberFormatException.

Common situations: Passing a float where the schema demands an int (e.g. partition count of 3.0); passing true/false for a numeric flag; missing values that deserialize to null; copy/pasting from a config that used scientific notation; using a JSON array where a single int was expected.

Related errors


AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03). Data as JSON: /data/errors/1ebe83382dc9d2ab.json. Report an issue: GitHub.