alibaba/nacos · info · NacosException

304

304

Error message

not modified

What it means

Thrown by callServerBytes() when the server returns HTTP 304 Not Modified. Code is NOT_MODIFIED (304). Same semantics as error 625 but for byte[] responses (skill download path). This signals the client's cached skill artifact is still current — not an error. Used by reqApiBytes(), which does NOT short-circuit on 304 (it retries across servers before the 304 surfaces as a retry-exhaustion error).

Source

Thrown at client/src/main/java/com/alibaba/nacos/client/ai/remote/AiHttpClientProxy.java:704

    
    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();
        header.addAll(securityHeaders);
        
        String url = buildUrl(server, api);
        
        try {
            HttpRestResult<byte[]> restResult = nacosRestTemplate.get(url, header,
                Query.newInstance().initParams(params), byte[].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);
        }
    }
    
    /**
     * Variant of {@link #callServerBytes} that exposes the raw {@link HttpRestResult} so callers
     * can inspect response headers (e.g. {@code X-Nacos-Skill-Md5}). Status code translation rules
     * mirror {@link #callServerBytes}: 304 raises {@link NacosException#NOT_MODIFIED}, 403
     * triggers a security re-login before bubbling the original status code up.

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Use querySkill() (via reqApiBytesWithHeader) instead of downloadSkill() (via reqApiBytes) when you need 304 propagation — the header variant short-circuits on 304.
  2. Catch NacosException.NOT_MODIFIED at the call site and treat it as 'cache still valid'.
  3. Ensure you pass the correct cached md5 to avoid unnecessary full downloads.

Example fix

// before: downloadSkill retries 304 across all servers
try {
    byte[] zip = aiService.downloadSkill("skill", "1.0", null);
} catch (NacosException e) {
    // if 304, this surfaces as error 622 (retry exhaustion) with code 304
}

// after: use querySkill for proper 304 handling
try {
    SkillQueryResponse resp = aiService.querySkill("skill", "1.0", null, cachedMd5);
} catch (NacosException e) {
    if (e.getErrCode() == NacosException.NOT_MODIFIED) {
        // cached skill ZIP is still current
        return;
    }
    throw e;
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
    byte[] zip = aiService.downloadSkill(name, ver, label);
} catch (NacosException e) {
    // reqApiBytes does NOT short-circuit on 304 — it retries, so 304 surfaces as error 622
    // Prefer querySkill() for 304-aware conditional downloads
    if (e.getErrCode() == NacosException.NOT_MODIFIED) {
        log.debug("Skill unchanged");
        return cachedZip;
    }
    throw e;
}

Prevention

When it happens

Trigger: A conditional skill-download GET where the server matches the client's md5 and returns 304. Because reqApiBytes retries on 304, this exception is caught and retried on every server before the final retry-exhaustion exception (error 622) is thrown with the 304 code.

Common situations: Repeated skill downloads with an unchanged md5. Developers expecting byte[] data but getting 304. The retry-on-304 behavior in reqApiBytes means 304 effectively becomes a retry-exhaustion error (error 622), not a clean 304 signal.

Related errors


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/39aea976d716b18a. Report an issue: GitHub.