quarkusio/quarkus · error · IllegalArgumentException

Channel cannot be blank

Error message

Channel cannot be blank

What it means

Quarkus Redis pub/sub validation: subscribe() rejects channel names that are null or blank because Redis PUB/SUB requires non-empty channel strings. A blank channel would produce a malformed SUBSCRIBE command that Lettuce/Redis cannot resolve.

Source

Thrown at extensions/redis-client/runtime/src/main/java/io/quarkus/redis/runtime/datasource/ReactivePubSubCommandsImpl.java:166

        return RedisConnections.withNewLongLivedConnection(client, conn -> {
            RedisAPI api = RedisAPI.api(conn);
            ReactiveRedisPatternSubscriberImpl subscriber = new ReactiveRedisPatternSubscriberImpl(conn, api, patterns,
                    onMessage, onEnd, onException);
            return subscriber.subscribe()
                    .replaceWith(subscriber);
        });
    }

    private void validateChannels(List<String> channels) {
        notNullOrEmpty(channels, "channels");

        for (String pattern : channels) {
            if (pattern == null) {
                throw new IllegalArgumentException("Channel must not be null");
            }
            if (pattern.isBlank()) {
                throw new IllegalArgumentException("Channel cannot be blank");
            }
        }
    }

    @Override
    public Uni<ReactiveRedisSubscriber> subscribe(List<String> channels, Consumer<V> onMessage, Runnable onEnd,
            Consumer<Throwable> onException) {
        nonNull(onMessage, "onMessage");
        validateChannels(channels);

        return RedisConnections.withNewLongLivedConnection(client, conn -> {
            RedisAPI api = RedisAPI.api(conn);
            ReactiveAbstractRedisSubscriberImpl subscriber = new ReactiveAbstractRedisSubscriberImpl(conn, api,
                    channels, (channel, value) -> onMessage.accept(value), onEnd, onException);
            return subscriber.subscribe()
                    .replaceWith(subscriber);
        });
    }

View on GitHub (pinned to e1c734241f)

Solutions

  1. Set a non-blank channel name before calling subscribe
  2. Trim/normalize configured channel names and fail fast at startup if blank
  3. Filter or validate the list before subscribing

Example fix

// before
String channel = config.get("topic");
redis.subscribe(List.of(channel), msg -> {}, () -> {});
// after
String channel = config.get("topic");
Objects.requireNonNull(channel, "channel");
if (channel.isBlank()) throw new IllegalStateException("topic config must not be blank");
redis.subscribe(List.of(channel), msg -> {}, () -> {});
Defensive patterns

Strategy: validation

Validate before calling

List<String> safeChannels = channels == null ? List.of() : channels;
if (safeChannels.isEmpty() || safeChannels.stream().anyMatch(c -> c == null || c.isBlank())) {
    throw new IllegalArgumentException("all channels must be non-blank strings");
}

Type guard

static boolean isValidChannels(List<String> channels) {
    return channels != null && !channels.isEmpty()
        && channels.stream().allMatch(c -> c != null && !c.isBlank());
}

Try / catch

try {
    redis.subscribe(channels, onMessage, onEnd);
} catch (IllegalArgumentException e) {
    log.error("Invalid pub/sub channel: " + e.getMessage());
}

Prevention

When it happens

Trigger: Calling ReactivePubSubCommandsImpl.subscribe(List.of(""), ...) or subscribe(List.of(" "), ...) or passing a list containing a blank entry; also psubscribe with blank patterns via the same validateChannels path.

Common situations: Channel names built from configuration properties or environment variables that are empty/whitespace; dynamically computed topic names where string interpolation yields an empty string; deserialized payloads missing the channel field.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/6f0a38b326c43a8c. Report an issue: GitHub.