alibaba/nacos · error · IllegalArgumentException
Agent replacement must not be null
Error message
Agent replacement must not be null
What it means
The tryUpdateAgent method requires a non-null Agent replacement object containing the writable fields for a CAS (compare-and-set) metadata update. A null replacement means the caller has no data to write, which is a programming error.
Source
Thrown at ai/src/main/java/com/alibaba/nacos/ai/service/agent/AgentPersistenceService.java:1083
throw new IllegalArgumentException("Agent Version agentName does not match request");
}
if (version.getStatus() != null
&& !AiConstants.Agent.VERSION_STATUS_ONLINE.equals(version.getStatus())) {
throw new IllegalArgumentException("Agent Version status must be online");
}
if (version.getContentDigest() != null || version.getCreateTime() != null
|| version.getUpdateTime() != null) {
throw new IllegalArgumentException(
"Agent Version must not contain read-only projection fields");
}
if (preferredLatest != null && !version.getVersion().equals(preferredLatest)) {
throw new IllegalArgumentException("preferredLatest must target the created Version");
}
}
private void validateAgentUpdateInputs(Agent replacement) {
if (replacement == null) {
throw new IllegalArgumentException("Agent replacement must not be null");
}
AgentValidationUtils.validateNamespaceId(replacement.getNamespaceId());
AgentValidationUtils.validateAgentName(replacement.getAgentName());
if (replacement.getVersionInfo() != null || replacement.getVersionCatalog() != null
|| replacement.getMetaVersion() != null || replacement.getCreateTime() != null
|| replacement.getUpdateTime() != null) {
throw new IllegalArgumentException(
"Agent update input must not contain read-only projection fields");
}
}
private Agent normalizeAgentUpdate(Agent source, Agent current) {
Agent result = new Agent();
result.setNamespaceId(source.getNamespaceId());
result.setAgentName(source.getAgentName());
result.setDisplayName(source.getDisplayName());
result.setDescription(source.getDescription());
result.setIconUrl(source.getIconUrl());View on GitHub (pinned to 9b989acdf1)
Solutions
- Ensure the Agent replacement object is constructed and populated before calling tryUpdateAgent.
- Validate non-null at the controller/service boundary before delegating to tryUpdateAgent.
- Check the HTTP request body is valid JSON with the expected Agent fields.
Example fix
// before
persistenceService.tryUpdateAgent(null, current); // throws
// after
Agent replacement = new Agent();
replacement.setNamespaceId("public");
replacement.setAgentName("my-agent");
replacement.setDisplayName("Updated Name");
persistenceService.tryUpdateAgent(replacement, current); Defensive patterns
Strategy: validation
Validate before calling
if (replacement == null) {
throw new IllegalArgumentException("Agent replacement must not be null");
} Type guard
boolean isUpdateableAgent(Agent a) {
return a != null && a.getNamespaceId() != null && a.getAgentName() != null;
} Prevention
- Validate the request body is non-null at the controller layer before calling the service.
- Use @RequestBody(required = true) or equivalent binding to reject empty bodies early.
When it happens
Trigger: Calling AgentPersistenceService.tryUpdateAgent(null, current) or the Agent update flow (PUT /v3/admin/ai/agent) with a null Agent body. The application service that reloads and authorizes the Resource before each retry passes the replacement down; a null reaches this method when upstream request binding fails to produce an Agent object.
Common situations: The HTTP PUT request body is empty or malformed so Spring binding yields null. An internal retry loop passes null when the previous attempt produced no replacement. A code path calls tryUpdateAgent before validating the request object.
Related errors
- Agent update input must not contain read-only projection fie
- Agent publish request must not be null
- AgentResourceExt must not be null
- Online Agent Version must contain callInterfaces
- Agent Version namespaceId does not match request
AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14).
Data as JSON: /api/errors/2f2b19559b18645c.
Report an issue: GitHub.