apache/shenyu · error · ShenyuException
group param invalid
Error message
group param invalid:%s
What it means
In the HTTP long-polling data sync listener, each gateway client sends a request parameter per config group (PLUGIN, SELECTOR, RULE, ...) in the format "<md5>,<lastModifyTime>". compareChangedGroup splits that parameter on ','; if the parameter is missing or doesn't contain exactly two comma-separated parts, it throws ShenyuException. This guards the long-polling contract between gateway and admin.
Solutions
- Use the official shenyu-sync-data-http-client instead of custom HTTP calls, so parameters are built as "md5,modifyTime" per group.
- Check the request URL sent by the gateway; ensure every ConfigGroupEnum name has a `<md5>,<lastModifyTime>` value, URL-encoded.
- Align gateway and admin versions — the long-polling parameter format must match on both sides.
- If behind a proxy, confirm query strings are not being rewritten or truncated.
Example fix
// before curl 'http://admin:9095/configs/listener?PLUGIN=abc' // after curl 'http://admin:9095/configs/listener?PLUGIN=abc123def,1690000000000&SELECTOR=...,&RULE=...'
Defensive patterns
Strategy: validation
Validate before calling
String param = group + "=" + md5 + "," + lastModifyTime;
if (md5 == null || !md5.matches("[0-9a-f]{32}")) throw new IllegalStateException("bad md5 for " + group); Try / catch
try {
listener.compareChangedGroup(request);
} catch (ShenyuException e) {
LOG.warn("malformed long-polling param: {}", e.getMessage());
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
} Prevention
- Use the official shenyu http sync client rather than hand-built requests
- Always URL-encode the md5,modifyTime pair
- Keep gateway and admin versions aligned
When it happens
Trigger: A gateway (or any HTTP client) calls the admin /configs/listener endpoint without a `group` query parameter, or with a value that has no comma or more than one comma, e.g. `?PLUGIN=abc123` instead of `?PLUGIN=abc123,1690000000000`.
Common situations: Hand-rolled scripts or curl calls hitting the listener endpoint; a gateway version whose long-polling wire format differs from the admin's (version skew after upgrade); proxies/gateways stripping or truncating query parameters; sending md5 values that contain characters a URL-encoding layer mangled.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- websocket on client open failed, namespaceId is null
- namespaceId can not be null
- Failed to get Swagger document, HTTP status code:
- Response body is empty
- Max response body size must not be negative
AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12).
Data as JSON: /api/errors/f2b3e5c111a49ef3.
Report an issue: GitHub.
Appendix: source
Thrown at shenyu-admin/src/main/java/org/apache/shenyu/admin/listener/http/HttpLongPollingDataChangedListener.java:214
@Override
protected void afterProxySelectorChanged(final List<ProxySelectorData> changed, final DataEventTypeEnum eventType, final String namespaceId) {
scheduler.execute(new DataChangeTask(ConfigGroupEnum.PROXY_SELECTOR, namespaceId));
}
@Override
protected void afterDiscoveryUpstreamDataChanged(final List<DiscoverySyncData> changed, final DataEventTypeEnum eventType, final String namespaceId) {
scheduler.execute(new DataChangeTask(ConfigGroupEnum.DISCOVER_UPSTREAM, namespaceId));
}
private List<ConfigGroupEnum> compareChangedGroup(final HttpServletRequest request) {
List<ConfigGroupEnum> changedGroup = new ArrayList<>(ConfigGroupEnum.values().length);
String namespaceId = getNamespaceId(request);
for (ConfigGroupEnum group : ConfigGroupEnum.values()) {
// md5,lastModifyTime
String[] params = StringUtils.split(request.getParameter(group.name()), ',');
if (Objects.isNull(params) || params.length != 2) {
throw new ShenyuException("group param invalid:" + request.getParameter(group.name()));
}
String clientMd5 = params[0];
long clientModifyTime = NumberUtils.toLong(params[1]);
ConfigDataCache serverCache = CACHE.get(buildCacheKey(namespaceId, group.name()));
// do check.
if (this.checkCacheDelayAndUpdate(serverCache, clientMd5, clientModifyTime)) {
changedGroup.add(group);
}
}
return changedGroup;
}
public static String buildCacheKey(final String namespaceId, final String group) {
return namespaceId + "_" + group;
}
/**View on GitHub (pinned to 567142e072)