apache/pulsar · error · IllegalArgumentException

Field '${name}' must be a Positive Number

Error message

Field '${name}' must be a Positive Number

What it means

ValidatorImpls.PositiveNumberValidator.validateField throws IllegalArgumentException when a value is either not a Number at all or is a Number with doubleValue() <= 0 (or < 0 when includeZero=true). Note it silently accepts null (returns early), so this error is about wrong type or non-positive values.

Source

Thrown at pulsar-config-validation/src/main/java/org/apache/pulsar/config/validation/ValidatorImpls.java:62

            this.includeZero = (boolean) params.get(ConfigValidationAnnotations.ValidatorParams.INCLUDE_ZERO);
        }

        public static void validateField(String name, boolean includeZero, Object o) {
            if (o == null) {
                return;
            }
            if (o instanceof Number) {
                if (includeZero) {
                    if (((Number) o).doubleValue() >= 0.0) {
                        return;
                    }
                } else {
                    if (((Number) o).doubleValue() > 0.0) {
                        return;
                    }
                }
            }
            throw new IllegalArgumentException(String.format("Field '%s' must be a Positive Number", name));
        }

        @Override
        public void validateField(String name, Object o) {
            validateField(name, this.includeZero, o);
        }
    }

    /**
     * Validates if an object is not null.
     */

    public static class NotNullValidator extends Validator {

        @Override
        public void validateField(String name, Object o) {
            if (o == null) {
                throw new IllegalArgumentException(String.format("Field '%s' cannot be null!", name));

View on GitHub (pinned to 820761864e)

Solutions

  1. Set the field to a number strictly greater than 0 (or >= 0 if the validator was created with INCLUDE_ZERO)
  2. If 0 is a legitimate value, use the INCLUDE_ZERO validator param for that field
  3. Remove units/symbols from the value ('5s' -> numeric field expecting milliseconds, use 5000)
  4. If null should be rejected too, add a NotNullValidator alongside this one, since PositiveNumberValidator passes null through

Example fix

# before
brokerClientOperationTimeoutSeconds: -1
# after
brokerClientOperationTimeoutSeconds: 30
Defensive patterns

Strategy: validation

Validate before calling

// before validateConfig
Object v = conf.get("brokerClientOperationTimeoutSeconds");
if (v != null && (!(v instanceof Number) || ((Number) v).doubleValue() <= 0))
    throw new IllegalStateException(v + " is not a positive number");

Type guard

static boolean isPositive(Number n) { return n != null && n.doubleValue() > 0.0; }

Try / catch

try {
    ConfigValidation.validateConfig(conf);
} catch (IllegalArgumentException e) {
    throw new IllegalStateException("Positive-number config violation: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: A config field annotated with @PositiveNumberValidator (or validated via PositiveNumberValidator.validateField) given a negative number, zero without includeZero=true, or a non-numeric value (e.g. a String that never got converted) during ConfigValidation.validateConfig.

Common situations: Setting a timeout/port/interval to 0 or a negative number in broker.conf; values like '-1' intended as 'unlimited' where the validator demands > 0; YAML unquoted strings arriving as non-Number objects.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/67b9701379f7df30. Report an issue: GitHub.