apache/pulsar · error · IllegalArgumentException

Field ${name} must be an Iterable but was a ${field.getClass

Error message

Field ${name} must be an Iterable but was a ${field.getClass()}

What it means

The list-validator NestableFieldValidator throws IllegalArgumentException when the field is non-null but is not an Iterable, i.e. a list-typed config field was given a scalar value. Each element is otherwise validated with the nested validator.

Source

Thrown at pulsar-config-validation/src/main/java/org/apache/pulsar/config/validation/ConfigValidationUtils.java:92

        return new NestableFieldValidator() {
            @Override
            public void validateField(String pd, String name, Object field)
                    throws IllegalArgumentException {

                if (field == null) {
                    if (notNull) {
                        throw new IllegalArgumentException("Field " + name + " must not be null");
                    } else {
                        return;
                    }
                }
                if (field instanceof Iterable) {
                    for (Object e : (Iterable) field) {
                        validator.validateField(pd + "Each element of the list ", name, e);
                    }
                    return;
                }
                throw new IllegalArgumentException(
                        "Field " + name + " must be an Iterable but was a " + field.getClass());
            }
        };
    }

    /**
     * Returns a new NestableFieldValidator for a Map of key to val.
     *
     * @param key     the Class of keys in the map
     * @param val     the Class of values in the map
     * @param notNull whether or not a value of null is valid
     * @return a NestableFieldValidator for a Map of key to val
     */
    public static NestableFieldValidator mapFv(Class<?> key, Class<?> val,
                                               boolean notNull) {
        return mapFv(fv(key, false), fv(val, false), notNull);
    }

View on GitHub (pinned to 820761864e)

Solutions

  1. Provide the value as a real collection (YAML dash list or JSON array)
  2. If the framework supports delimited strings, split into a List before validation (e.g. Arrays.asList(value.split(",")))
  3. Fix programmatic construction to assign List<String> (or the declared Iterable type) rather than String

Example fix

# before
servers: zk1,zk2
# after
servers:
  - zk1
  - zk2
Defensive patterns

Strategy: type-guard

Validate before calling

// before validateConfig
Object servers = conf.get("servers");
if (!(servers instanceof java.util.List)) {
    if (servers instanceof String) conf.put("servers", java.util.Arrays.asList(((String) servers).split(",")));
    else throw new IllegalStateException("servers must be a list");
}

Type guard

static boolean isList(Object o) { return o instanceof java.util.List; }

Try / catch

try {
    ConfigValidation.validateConfig(conf);
} catch (IllegalArgumentException e) {
    throw new IllegalStateException("List field given scalar value: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: A list-typed config property set to a single scalar (String or Number) instead of a collection — common when using properties files where list syntax collapses to one string, or YAML where the value was not written as a list.

Common situations: Writing 'servers=zk1,zk2' in a properties file where the validator expects an actual List/Iterable object; YAML 'servers: zk1' instead of a dash list; programmatic config built with a String instead of List<String>.

Related errors


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