TheAlgorithms/Java · error · IllegalArgumentException

Listener must not be null

Error message

Listener must not be null

What it means

Thrown by FIFOCache.Builder.evictionListener(BiConsumer) when the listener is null. The listener is invoked on every eviction/overwrite, and a null listener would cause an NPE deep inside put/removeKey rather than at the configuration site. The guard ensures the failure surfaces at configuration time.

Source

Thrown at src/main/java/com/thealgorithms/datastructures/caches/FIFOCache.java:519

         */
        public Builder<K, V> defaultTTL(long ttlMillis) {
            if (ttlMillis < 0) {
                throw new IllegalArgumentException("Default TTL must be >= 0");
            }
            this.defaultTTL = ttlMillis;
            return this;
        }

        /**
         * Sets an eviction listener to be notified when entries are evicted from the cache.
         *
         * @param listener a {@link BiConsumer} that accepts evicted keys and values; must not be {@code null}
         * @return this builder instance for chaining
         * @throws IllegalArgumentException if {@code listener} is {@code null}
         */
        public Builder<K, V> evictionListener(BiConsumer<K, V> listener) {
            if (listener == null) {
                throw new IllegalArgumentException("Listener must not be null");
            }
            this.evictionListener = listener;
            return this;
        }

        /**
         * Builds and returns a new {@link FIFOCache} instance with the configured parameters.
         *
         * @return a fully configured {@code FIFOCache} instance
         */
        public FIFOCache<K, V> build() {
            return new FIFOCache<>(this);
        }

        /**
         * Sets the eviction strategy used to determine when to clean up expired entries.
         *
         * @param strategy an {@link EvictionStrategy} implementation; must not be {@code null}

View on GitHub (pinned to fdfb9a395b)

Solutions

  1. Provide a no-op listener instead of null: (k,v) -> {}.
  2. Guard the wiring: if (listener != null) builder.evictionListener(listener);
  3. Make the listener field required in your DI configuration so null cannot be injected.

Example fix

// before
builder.evictionListener(maybeListener);
// after
builder.evictionListener(maybeListener != null ? maybeListener : (k, v) -> {});
Defensive patterns

Strategy: validation

Validate before calling

BiConsumer<K, V> listener = maybeListener != null ? maybeListener : (k, v) -> {};
builder.evictionListener(listener);

Type guard

static <K, V> boolean isUsableListener(BiConsumer<K, V> listener) {
    return listener != null;
}

Prevention

When it happens

Trigger: builder.evictionListener(null); builder.evictionListener(metricsRegistrar) where metricsRegistrar was never initialized; conditional wiring where the listener is only set in some environments.

Common situations: Feature-flagged metrics where the flag is off; DI misconfiguration that injects null; test builders that omit the listener.

Related errors


AI-assisted analysis of TheAlgorithms/Java@fdfb9a395b (2026-08-13). Data as JSON: /api/errors/a9bca851241e1285. Report an issue: GitHub.