alibaba/nacos · info · NacosException
NOT_MODIFIED
NOT_MODIFIED
Error message
not modified
What it means
Thrown by callServer() (String variant) when the Nacos server returns HTTP 304 Not Modified. Code is NOT_MODIFIED (304). This is NOT a true error — it is a control-flow signal indicating the client's cached content (identified by md5/timestamp) is still current and the server has no newer data to return. The caller should treat this as 'cache hit, no update needed'.
Source
Thrown at client/src/main/java/com/alibaba/nacos/client/ai/remote/AiHttpClientProxy.java:673
private String callServer(String api, Map<String, String> params, String server,
RequestResource resource)
throws NacosException {
Map<String, String> securityHeaders = securityProxy.getIdentityContext(resource);
Header header = Header.newInstance();
header.addAll(securityHeaders);
String url = buildUrl(server, api);
try {
HttpRestResult<String> restResult = nacosRestTemplate.get(url, header,
Query.newInstance().initParams(params), String.class);
if (restResult.ok()) {
return restResult.getData();
}
if (HttpURLConnection.HTTP_NOT_MODIFIED == restResult.getCode()) {
throw new NacosException(NacosException.NOT_MODIFIED, "not modified");
}
if (HttpURLConnection.HTTP_FORBIDDEN == restResult.getCode()) {
securityProxy.reLogin();
}
throw new NacosException(restResult.getCode(), restResult.getMessage());
} catch (NacosException e) {
throw e;
} catch (Exception e) {
LOGGER.error("[AI-HTTP] Failed to request {}", url, e);
throw new NacosException(NacosException.SERVER_ERROR, e);
}
}
private byte[] callServerBytes(String api, Map<String, String> params, String server,
RequestResource resource)
throws NacosException {
Map<String, String> securityHeaders = securityProxy.getIdentityContext(resource);
Header header = Header.newInstance();View on GitHub (pinned to 9b989acdf1)
Solutions
- Catch NacosException with code NOT_MODIFIED and treat it as a no-op (cache is still valid), not as a failure.
- If using reqApi directly (which retries 304s), consider switching to a header-returning variant that propagates 304 immediately.
- Ensure your md5/etag comparison logic is correct so you only send conditional requests when you have a valid cached version.
Example fix
// before: treating 304 as an error
try {
String data = proxy.reqApi(api, params, resource);
} catch (NacosException e) {
log.error("Request failed", e); // wrongly logs 304 as error
}
// after: handle 304 explicitly
try {
String data = proxy.reqApi(api, params, resource);
} catch (NacosException e) {
if (e.getErrCode() == NacosException.NOT_MODIFIED) {
// cached version is still current, no action needed
return cachedData;
}
throw e;
} Defensive patterns
Strategy: try-catch
Try / catch
try {
String data = proxy.reqApi(api, params, resource);
} catch (NacosException e) {
if (e.getErrCode() == NacosException.NOT_MODIFIED) {
// content unchanged — use cached value
return cachedValue;
}
throw e; // real error, propagate
} Prevention
- Always check for NOT_MODIFIED code in catch blocks for conditional queries.
- Use header-returning variants (reqApiBytesWithHeader, reqApiStringWithHeader) which propagate 304 immediately.
- Do not log or alert on 304 responses.
When it happens
Trigger: A conditional GET request (e.g., via reqApi with an md5 parameter) where the server determines the client's cached version matches. The server responds with 304 instead of resending the body. This happens on polling/watch cycles where content hasn't changed.
Common situations: Normal operation of long-poll or conditional-query patterns — 304 is expected on most polls when data is unchanged. Developers unfamiliar with the pattern may treat it as an error. The reqApi retry loop does NOT short-circuit on 304 (unlike reqApiBytesWithHeader), so 304 would be retried across all servers before surfacing.
Related errors
AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14).
Data as JSON: /api/errors/d521324cc793f4bf.
Report an issue: GitHub.