{"record":{"id":"c270d4930c824271","repo":"alibaba/nacos","slug":"server-error","errorCode":"SERVER_ERROR","errorMessage":"Agent Version content cannot be saved","messagePattern":"Agent Version content cannot be saved","errorType":"exception","errorClass":"NacosException","httpStatus":500,"severity":"error","filePath":"ai/src/main/java/com/alibaba/nacos/ai/service/agent/storage/AgentVersionStorageService.java","lineNumber":142,"sourceCode":"    /**\n     * Save content that was previously returned by {@link #prepare(String, String, String,\n     * AgentVersionContent)}.\n     *\n     * <p>The provider and key captured during preparation are used even when the current storage\n     * provider configuration has changed.</p>\n     *\n     * @param prepared prepared Agent Version content\n     * @throws NacosException when the selected storage provider fails\n     */\n    public void save(PreparedAgentVersionWrite prepared) throws NacosException {\n        if (prepared == null) {\n            throw new IllegalArgumentException(\"Prepared Agent Version content must not be null\");\n        }\n        StorageKey storageKey = prepared.getStorageKey();\n        try {\n            route(storageKey).save(storageKey, prepared.getBytes());\n        } catch (IllegalArgumentException e) {\n            throw new NacosException(NacosException.SERVER_ERROR,\n                \"Agent Version content cannot be saved\", e);\n        }\n    }\n    \n    /**\n     * Read, verify, and deserialize one Agent Version content object.\n     *\n     * <p>Size and digest are checked against the exact bytes returned by AI Storage before JSON\n     * decoding. Unverified content is never returned.</p>\n     *\n     * @param descriptor Version storage pointer\n     * @return verified Agent Version content\n     * @throws NacosException when content is missing, corrupted, or cannot be read\n     */\n    public AgentVersionContent load(AgentVersionStorageDescriptor descriptor)\n        throws NacosException {\n        StorageKey storageKey = checkedStorageKey(descriptor);\n        byte[] bytes;","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/ai/src/main/java/com/alibaba/nacos/ai/service/agent/storage/AgentVersionStorageService.java#L124-L160","documentation":"Thrown by AgentVersionStorageService.save(PreparedAgentVersionWrite) when persisting prepared Agent Version bytes fails. The method routes to the selected AiResourceStorage and calls its save(); any IllegalArgumentException surfaced during routing (blank StorageKey.provider) or from the storage implementation's own save() (rejected content/key) is wrapped into a SERVER_ERROR NacosException. This is an internal persistence failure, not a caller-input problem.","triggerScenarios":"Calling AgentVersionStorageService.save(prepared) or the convenience overload save(namespaceId, agentName, version, content) where the resolved StorageKey has a blank provider, or the underlying AiResourceStorage.save() throws IllegalArgumentException because the content bytes or key violate provider-specific invariants.","commonSituations":"A PreparedAgentVersionWrite was built from a stale or hand-constructed descriptor whose provider field is empty; the configured storage plugin rejects oversized or malformed serialized content; the AgentVersionContentSerializer produced bytes the storage layer cannot accept.","solutions":["Inspect the wrapped cause (NacosException.getCause()) to see which IllegalArgumentException fired and its message — it identifies whether routing or the storage save rejected the write.","Ensure the PreparedAgentVersionWrite passed to save() was produced by AgentVersionStorageService.prepare(...) so its StorageKey (provider + key) is valid and non-blank.","Verify the AgentVersionContent object is well-formed before preparation (non-null kind, schemaVersion, valid JSON-serializable fields) so the serializer does not emit bytes the storage rejects.","If the storage implementation imposes size/format limits, reduce the content payload or switch to a storage provider that accepts it."],"exampleFix":"// before\nAgentVersionStorageDescriptor desc = new AgentVersionStorageDescriptor();\ndesc.setProvider(\"\"); // blank provider\nPreparedAgentVersionWrite prepared = service.prepare(ns, agent, ver, content);\nservice.save(prepared); // fails: IllegalArgumentException from routing\n\n// after\n// Always go through prepare(); it resolves the provider from config\nPreparedAgentVersionWrite prepared = service.prepare(ns, agent, ver, content);\nservice.save(prepared);","handlingStrategy":"try-catch","validationCode":"// Validate before save\nif (prepared == null) {\n    throw new IllegalArgumentException(\"prepared must not be null\");\n}\nif (prepared.getStorageKey() == null\n    || StringUtils.isBlank(prepared.getStorageKey().getProvider())) {\n    throw new IllegalStateException(\"StorageKey.provider is blank; rebuild via prepare()\");\n}\nif (prepared.getBytes() == null || prepared.getBytes().length == 0) {\n    throw new IllegalArgumentException(\"Serialized content is empty\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    versionStorageService.save(prepared);\n} catch (NacosException e) {\n    if (e.getErrCode() == NacosException.SERVER_ERROR) {\n        Throwable cause = e.getCause();\n        log.error(\"Agent Version save failed: {}\", cause != null ? cause.getMessage() : e.getMessage(), e);\n    }\n    throw e;\n}","preventionTips":["Always build PreparedAgentVersionWrite via AgentVersionStorageService.prepare() rather than constructing it manually.","Do not mutate the descriptor's provider/key between prepare() and save().","Log the wrapped cause to distinguish routing failures from storage rejections."],"tags":["agent-version","storage","persistence","server-error"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}