apache/pulsar · error · org.apache.pulsar.broker.admin.RestException
entryFilterNames can't be empty. To remove entry filters use
Error message
entryFilterNames can't be empty. To remove entry filters use the remove method.
What it means
When updating a topic/namespace policy with entry filters, an entryFilterNames value that is blank or contains only separators/whitespace is rejected with HTTP 400. Entry filters are only ever set or replaced via this API; removal is a separate operation (setEntryFilters with null / the remove endpoint), so an empty list is treated as a caller mistake rather than a 'clear' request.
Source
Thrown at pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/AdminResource.java:956
checkArgument(retention.getRetentionTimeInMinutes() >= -1,
"Invalid retention policy: time limit must be >= -1");
checkArgument((retention.getRetentionTimeInMinutes() != 0 && retention.getRetentionSizeInMB() != 0)
|| (retention.getRetentionTimeInMinutes() == 0 && retention.getRetentionSizeInMB() == 0),
"Invalid retention policy: Setting a single time or size limit to 0 is invalid when "
+ "one of the limits has a non-zero value. Use the value of -1 instead of 0 to ignore a "
+ "specific limit. To disable retention both limits must be set to 0.");
}
protected void validateEntryFilters(EntryFilters entryFilters) {
if (entryFilters == null) {
// remove entry filters
return;
}
if (StringUtils.isBlank(entryFilters.getEntryFilterNames())
|| Arrays.stream(entryFilters.getEntryFilterNames().split(","))
.filter(n -> StringUtils.isNotBlank(n))
.findAny().isEmpty()) {
throw new RestException(new RestException(Status.BAD_REQUEST,
"entryFilterNames can't be empty. To remove entry filters use the remove method."));
}
try {
pulsar().getBrokerService().getEntryFilterProvider()
.validateEntryFilters(entryFilters.getEntryFilterNames());
} catch (InvalidEntryFilterException ex) {
throw new RestException(new RestException(Status.BAD_REQUEST, ex));
}
}
/**
* Check current exception whether is redirect exception.
*
* @param ex The throwable.
* @return Whether is redirect exception
*/
protected static boolean isRedirectException(Throwable ex) {
Throwable realCause = FutureUtil.unwrapCompletionException(ex);View on GitHub (pinned to 820761864e)
Solutions
- If you intend to REMOVE filters, use the remove path: call the removeEntryFilters/DELETE API or send the update without setting entryFilterNames (null), not an empty string.
- If you intend to SET filters, populate entryFilterNames with at least one valid, non-blank filter class name, comma-separated for multiple.
- Trim/normalize your input before sending: filter out blank tokens and if none remain, switch to the remove call instead.
- Verify entry filters are enabled on the broker (entryFilterAvailablity / broker config) — but note the 400 here is purely about the empty name list, independent of filter validity.
Example fix
// before (400: blank filter list meant as 'clear')
admin.namespaces().setEntryFilters(ns, new EntryFiltersImpl().setEntryFilterNames(""));
// after: remove instead
admin.namespaces().removeEntryFilters(ns);
// or set real values
admin.namespaces().setEntryFilters(ns, new EntryFiltersImpl().setEntryFilterNames("com.acme.FilterA,com.acme.FilterB")); Defensive patterns
Strategy: validation
Validate before calling
// Java
String names = entryFilters.getEntryFilterNames();
boolean valid = names != null && Arrays.stream(names.split(",")).anyMatch(n -> !n.isBlank());
if (!valid) { admin.namespaces().removeEntryFilters(ns); return; } Try / catch
try {
admin.namespaces().setEntryFilters(ns, entryFilters);
} catch (PulsarAdminException.BadRequestException e) {
if (e.getMessage().contains("entryFilterNames can't be empty")) {
admin.namespaces().removeEntryFilters(ns); // removal is the remove API, not empty list
}
} Prevention
- Never send EntryFilters with blank/whitespace-only entryFilterNames.
- Treat 'clear filters' as a distinct remove API call, not an empty set.
- Join filter lists defensively: filter blank tokens before joining with ','.
- Validate filter class names against the broker's configured filter provider before sending.
When it happens
Trigger: Calling the admin policy-update endpoint (e.g. POST/PUT namespace or topic policies) with an EntryFilters body where entryFilterNames is null/empty/whitespace or a comma string like ",, " — i.e. all split tokens blank.
Common situations: 1) Client code sends an empty EntryFilters object intending to clear filters. 2) A config template has entryFilterNames bound to an empty env var. 3) A UI joins filter names with ',' and the list was empty, producing ','.
Related errors
- The offloadPolicies must be specified for namespace offload.
- The bucket must be specified for namespace offload.
- The topic has a max partition index of %d, the number of par
- The driver is not supported, support value: ${supportedDrive
- cluster data is required
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/3334b5729f6b4470.
Report an issue: GitHub.