apache/pulsar · error · IllegalArgumentException

configProperties cannot be null

Error message

configProperties cannot be null

What it means

Constructor guard on TieredStorageConfiguration: the configProperties map is the sole source of driver/endpoint/bucket/credential settings, so a null map cannot yield a usable configuration. The public constructor rejects null immediately with IllegalArgumentException instead of failing later with NPEs.

Source

Thrown at tiered-storage/jcloud/src/main/java/org/apache/bookkeeper/mledger/offload/jcloud/provider/TieredStorageConfiguration.java:107

        return new TieredStorageConfiguration(map);
    }

    public static TieredStorageConfiguration create(Map<String, String> props) {
        return new TieredStorageConfiguration(props);
    }

    @Getter
    private final Map<String, String> configProperties;
    @Getter
    private Supplier<Credentials> credentials;
    private JCloudBlobStoreProvider provider;

    public TieredStorageConfiguration(Map<String, String> configProperties) {
        if (configProperties != null) {
            this.configProperties = configProperties;
        } else {
            throw new IllegalArgumentException("configProperties cannot be null");
        }
    }

    public List<String> getKeys(String property) {
        List<String> keys = new ArrayList<String> ();

        String bc = getBackwardCompatibleKey(property);
        if (StringUtils.isNotBlank(bc)) {
            keys.add(bc);
        }

        String key = getKeyName(property);
        if (StringUtils.isNotBlank(key)) {
            keys.add(key);
        }
        return keys;
    }

View on GitHub (pinned to 820761864e)

Solutions

  1. Pass an empty map (new HashMap<>()) instead of null if there are genuinely no properties.
  2. Load the map from broker.conf / offload policies before constructing the configuration.
  3. Add a null/empty check at the call site to surface the real source of the null map.
  4. In tests, build a minimal map with driver/endpoint/bucket keys.

Example fix

// before
TieredStorageConfiguration cfg = new TieredStorageConfiguration(null);
// after
Map<String,String> props = loadOffloadProperties();
TieredStorageConfiguration cfg = new TieredStorageConfiguration(
    props != null ? props : new HashMap<>());
Defensive patterns

Strategy: type-guard

Validate before calling

if (props == null) {
    props = new HashMap<>();
}
TieredStorageConfiguration cfg = new TieredStorageConfiguration(props);

Type guard

static boolean hasProperties(Map<String, String> props) {
    return props != null;
}

Try / catch

try {
    cfg = new TieredStorageConfiguration(props);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("configProperties cannot be null")) {
        cfg = new TieredStorageConfiguration(new HashMap<>());
    }
}

Prevention

When it happens

Trigger: Calling new TieredStorageConfiguration(null) — typically from code that loads a properties map from a file/keystore that returned null, or passes an uninitialized map variable.

Common situations: Plugin or custom offload driver constructing the config before properties are loaded; Properties-to-Map conversion returning null on missing resource; unit tests invoking the constructor with null.

Related errors


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