alibaba/spring-ai-alibaba · error · IllegalStateException
Cannot instantiate class {} for @class deserialization
Error message
Cannot instantiate class {} for @class deserialization What it means
JacksonDeserializer.valueFromNode resolves a @class type hint in the JSON via Class.forName(className); if the class is not on the classpath, it wraps the ClassNotFoundException in an IllegalStateException("Cannot instantiate class <name> for @class deserialization"). This prevents silently degrading typed data to maps when the declared type is unavailable.
Source
Thrown at spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/serializer/plain_text/jackson/JacksonDeserializer.java:313
copy.remove("@typeHint");
// Get Class from TypeReference using ObjectMapper's TypeFactory
Class<?> targetClass = objectMapper.getTypeFactory().constructType(ref).getRawClass();
yield deserializeWithStrategy(copy, targetClass, objectMapper, typeMapper);
}
if (valueNode.has("@class")) {
String className = valueNode.get("@class").asText();
if (!(typeHint != null && className.startsWith("java.util."))) {
ObjectNode copy = valueNode.deepCopy();
copy.remove("@class");
copy.remove("@typeHint");
try {
Class<?> clazz = Class.forName(className);
// Use unified deserialization strategy
yield deserializeWithStrategy(copy, clazz, objectMapper, typeMapper);
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot instantiate class " + className + " for @class deserialization", ex);
}
}
}
if (typeHint != null) {
ObjectNode copy = valueNode.deepCopy();
copy.remove("@typeHint");
copy.remove(TYPE_PROPERTY);
copy.remove("@class");
try {
Class<?> clazz = Class.forName(typeHint);
// Use unified deserialization strategy
yield deserializeWithStrategy(copy, clazz, objectMapper, typeMapper);
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Cannot instantiate class " + typeHint + " for @typeHint deserialization", ex);
}View on GitHub (pinned to f82da0b50f)
Solutions
- Add the jar/dependency containing the named class to the classpath
- Restore the original package/class name or keep a compatibility class during migration
- Re-serialize checkpoints with current classes, or delete old checkpoints
- Ensure both producer and consumer use the same spring-ai-alibaba versions
Example fix
// before // checkpoint written by com.old.pkg.MyState (class since moved) Object v = deserializer.valueFromNode(node); // IllegalStateException // after // keep a backwards-compatible alias or migrate the stored @class value // old: "@class":"com.old.pkg.MyState" // new: "@class":"com.new.pkg.MyState"
Defensive patterns
Strategy: try-catch
Validate before calling
// before deserializing, check the @class is resolvable
String className = valueNode.get("@class").asText();
try {
Class.forName(className);
} catch (ClassNotFoundException e) {
logger.warn("@class {} missing from classpath", className);
} Type guard
boolean classResolvable(String name) {
try { Class.forName(name); return true; }
catch (ClassNotFoundException e) { return false; }
} Try / catch
try {
return deserializer.valueFromNode(node);
} catch (IllegalStateException e) {
if (String.valueOf(e.getMessage()).contains("for @class deserialization")) {
// fall back to raw map or rebuild state from defaults
return objectMapper.convertValue(node, new TypeReference<Map<String,Object>>() {});
}
throw e;
} Prevention
- Keep DTO classes referenced in @class hints in a shared dependency
- Never rename/move classes referenced by persisted checkpoints without migration
- Align library versions between services exchanging serialized state
- Validate @class values against an allowlist at load time
When it happens
Trigger: Deserializing JSON produced elsewhere (another JVM, persisted checkpoint, studio/admin export) whose @class field names a class missing from the current application's classpath.
Common situations: Renamed/moved/removed classes after refactor; checkpoint saved by an older library version; missing dependency jar containing the class; serializing application-specific classes then deserializing in a different module.
Related errors
- Cannot instantiate class {} for @typeHint deserialization
- Status value cannot be null
- Unknown status: ${value}. Valid values are: pending, in_prog
- Cannot instantiate array type: {}
- Cannot instantiate array type from scalar payload: {}
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/fb1abfa91624d97e.
Report an issue: GitHub.