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
- Set a non-blank channel name before calling subscribe
- Trim/normalize configured channel names and fail fast at startup if blank
- 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
- Trim channel names read from config/environment
- Fail at application startup if a configured topic is blank
- Centralize topic-name constants instead of inline strings
- Write a unit test covering blank-channel rejection
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
- `count` must be strictly positive
- `timeout` must be positive
- `timeout` must not be `null`
- `timestamp` must not be `null`
- `" + name + "` must not be `null`
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/6f0a38b326c43a8c.
Report an issue: GitHub.