{"record":{"id":"d521324cc793f4bf","repo":"alibaba/nacos","slug":"not-modified","errorCode":"NOT_MODIFIED","errorMessage":"not modified","messagePattern":"not modified","errorType":"exception","errorClass":"NacosException","httpStatus":null,"severity":"info","filePath":"client/src/main/java/com/alibaba/nacos/client/ai/remote/AiHttpClientProxy.java","lineNumber":673,"sourceCode":"    \n    private String callServer(String api, Map<String, String> params, String server,\n        RequestResource resource)\n        throws NacosException {\n        Map<String, String> securityHeaders = securityProxy.getIdentityContext(resource);\n        Header header = Header.newInstance();\n        header.addAll(securityHeaders);\n        \n        String url = buildUrl(server, api);\n        \n        try {\n            HttpRestResult<String> restResult = nacosRestTemplate.get(url, header,\n                Query.newInstance().initParams(params), String.class);\n            \n            if (restResult.ok()) {\n                return restResult.getData();\n            }\n            if (HttpURLConnection.HTTP_NOT_MODIFIED == restResult.getCode()) {\n                throw new NacosException(NacosException.NOT_MODIFIED, \"not modified\");\n            }\n            if (HttpURLConnection.HTTP_FORBIDDEN == restResult.getCode()) {\n                securityProxy.reLogin();\n            }\n            throw new NacosException(restResult.getCode(), restResult.getMessage());\n        } catch (NacosException e) {\n            throw e;\n        } catch (Exception e) {\n            LOGGER.error(\"[AI-HTTP] Failed to request {}\", url, e);\n            throw new NacosException(NacosException.SERVER_ERROR, e);\n        }\n    }\n    \n    private byte[] callServerBytes(String api, Map<String, String> params, String server,\n        RequestResource resource)\n        throws NacosException {\n        Map<String, String> securityHeaders = securityProxy.getIdentityContext(resource);\n        Header header = Header.newInstance();","sourceCodeStart":655,"sourceCodeEnd":691,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/client/src/main/java/com/alibaba/nacos/client/ai/remote/AiHttpClientProxy.java#L655-L691","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: treating 304 as an error\ntry {\n    String data = proxy.reqApi(api, params, resource);\n} catch (NacosException e) {\n    log.error(\"Request failed\", e); // wrongly logs 304 as error\n}\n\n// after: handle 304 explicitly\ntry {\n    String data = proxy.reqApi(api, params, resource);\n} catch (NacosException e) {\n    if (e.getErrCode() == NacosException.NOT_MODIFIED) {\n        // cached version is still current, no action needed\n        return cachedData;\n    }\n    throw e;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    String data = proxy.reqApi(api, params, resource);\n} catch (NacosException e) {\n    if (e.getErrCode() == NacosException.NOT_MODIFIED) {\n        // content unchanged — use cached value\n        return cachedValue;\n    }\n    throw e; // real error, propagate\n}","preventionTips":["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."],"tags":["nacos","ai-client","http","not-modified","conditional-request","cache"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}