jwtk/jjwt · error · IllegalArgumentException

Value must be a positive integer.

Error message

Value must be a positive integer.

What it means

Thrown by PositiveIntegerConverter.applyFrom when a raw value destined for a parameter that must be a positive integer either cannot be converted to an int (overflow, fractional number, non-numeric string) or converts to a value <= 0. It is a parameter-conversion guard: the offending input is whatever Object was passed for that parameter (e.g. an expiration/leeway-style setting).

Source

Thrown at impl/src/main/java/io/jsonwebtoken/impl/lang/PositiveIntegerConverter.java:51

        Assert.notNull(o, "Argument cannot be null.");
        int i;
        if (o instanceof Byte || o instanceof Short || o instanceof Integer || o instanceof AtomicInteger) {
            i = ((Number) o).intValue();
        } else {  // could be Long, AtomicLong, Float, Decimal, BigInteger, BigDecimal, String, etc., all of which
            // may not be accurately converted into an Integer, either due to overflow or fractional values.  The
            // easiest way to account for all of them is to parse the string value as an int instead of testing all
            // the types:
            String sval = String.valueOf(o);
            try {
                i = Integer.parseInt(sval);
            } catch (NumberFormatException e) {
                String msg = "Value cannot be represented as a java.lang.Integer.";
                throw new IllegalArgumentException(msg, e);
            }
        }
        if (i <= 0) {
            String msg = "Value must be a positive integer.";
            throw new IllegalArgumentException(msg);
        }
        return i;
    }
}

View on GitHub (pinned to fb71496164)

Solutions

  1. Ensure the value is >= 1 before passing it.
  2. Clamp or validate: if (v <= 0) throw/adjust before setting the claim.
  3. Check upstream computation for off-by-one or sign errors that produced the non-positive value.

Example fix

// before
long seconds = (end - start) / 1000; // could be 0
jwtBuilder.claim("ttl", (int) seconds);
// after
int seconds = Math.max(1, (int) ((end - start) / 1000));
jwtBuilder.claim("ttl", seconds);
Defensive patterns

Strategy: validation

Validate before calling

int requirePositive(int v) {
    if (v <= 0) throw new IllegalArgumentException("Value must be a positive integer, got: " + v);
    return v;
}

Try / catch

try {
    converter.applyFrom(value);
} catch (IllegalArgumentException e) {
    if ("Value must be a positive integer.".equals(e.getMessage())) {
        // clamp or reject the non-positive input
    }
    throw e;
}

Prevention

When it happens

Trigger: Passing 0 or a negative number (or a string like "0", "-3") to any claim/converter configured with PositiveIntegerConverter.

Common situations: Zero initialized counters used as default values; negative offsets; computing a value like timeout = end - start that evaluated to <= 0.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of jwtk/jjwt@fb71496164 (2026-09-09). Data as JSON: /api/errors/75e55db7b766fe5c. Report an issue: GitHub.