{"record":{"id":"378ffdfbcddfd9d1","repo":"alibaba/spring-ai-alibaba","slug":"cannot-instantiate-class-for-typehint-deserial","errorCode":null,"errorMessage":"Cannot instantiate class {} for @typeHint deserialization","messagePattern":"Cannot instantiate class (.+?) for @typeHint deserialization","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/serializer/plain_text/jackson/JacksonDeserializer.java","lineNumber":329,"sourceCode":"\t\t\t\t\t}\n\t\t\t\t\tcatch (ClassNotFoundException ex) {\n\t\t\t\t\t\tthrow new IllegalStateException(\n\t\t\t\t\t\t\t\t\"Cannot instantiate class \" + className + \" for @class deserialization\", ex);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (typeHint != null) {\n\t\t\t\t\tObjectNode copy = valueNode.deepCopy();\n\t\t\t\t\tcopy.remove(\"@typeHint\");\n\t\t\t\t\tcopy.remove(TYPE_PROPERTY);\n\t\t\t\t\tcopy.remove(\"@class\");\n\t\t\t\t\ttry {\n\t\t\t\t\t\tClass<?> clazz = Class.forName(typeHint);\n\t\t\t\t\t\t// Use unified deserialization strategy\n\t\t\t\t\t\tyield deserializeWithStrategy(copy, clazz, objectMapper, typeMapper);\n\t\t\t\t\t}\n\t\t\t\t\tcatch (ClassNotFoundException ex) {\n\t\t\t\t\t\tthrow new IllegalStateException(\n\t\t\t\t\t\t\t\t\"Cannot instantiate class \" + typeHint + \" for @typeHint deserialization\", ex);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tMap<String, Object> result = new LinkedHashMap<>();\n\t\t\t\tvar fields = valueNode.fields();\n\t\t\t\twhile (fields.hasNext()) {\n\t\t\t\t\tvar entry = fields.next();\n\t\t\t\t\tString key = entry.getKey();\n\t\t\t\t\tif (\"@class\".equals(key) || \"@type\".equals(key) || \"@typeHint\".equals(key)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tresult.put(key, valueFromNode(entry.getValue(), objectMapper, typeMapper));\n\t\t\t\t}\n\t\t\t\tyield result;\n\t\t\t}\n\t\t\tcase BOOLEAN -> valueNode.asBoolean();\n\t\t\tcase NUMBER -> {\n\t\t\t\t// Preserve original number type logic","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-graph-core/src/main/java/com/alibaba/cloud/ai/graph/serializer/plain_text/jackson/JacksonDeserializer.java#L311-L347","documentation":"Same mechanism as the @class path: valueFromNode resolves the @typeHint metadata value with Class.forName(typeHint); when that class cannot be loaded, it throws IllegalStateException(\"Cannot instantiate class <name> for @typeHint deserialization\") wrapping the ClassNotFoundException.","triggerScenarios":"Deserializing JSON where the @typeHint field references a class absent from the runtime classpath — e.g. state serialized with custom typed collections/POJOs then read in an app/module that lacks those classes.","commonSituations":"Cross-service state exchange where one service has a DTO the other doesn't; version skew between services serializing checkpoints; removed classes after dependency upgrades.","solutions":["Add the missing class's artifact to the deserializing service's classpath","Keep shared state DTOs in a common module used by both producer and consumer","Align library versions across services so type hints resolve identically","Pre-serialize or migrate old payloads whose @typeHint points to removed classes"],"exampleFix":"// before\n// pom.xml of consumer lacks the module containing com.acme.TaskResult\nObject v = deserializer.valueFromNode(node); // IllegalStateException\n// after\n<dependency>\n  <groupId>com.acme</groupId>\n  <artifactId>task-models</artifactId>\n  <version>1.2.0</version>\n</dependency>","handlingStrategy":"try-catch","validationCode":"String hint = valueNode.get(\"@typeHint\").asText();\ntry {\n    Class.forName(hint);\n} catch (ClassNotFoundException e) {\n    logger.warn(\"@typeHint {} not on classpath\", hint);\n}","typeGuard":"boolean typeHintResolvable(String hint) {\n    try { Class.forName(hint); return true; }\n    catch (ClassNotFoundException e) { return false; }\n}","tryCatchPattern":"try {\n    return deserializer.valueFromNode(node);\n} catch (IllegalStateException e) {\n    if (String.valueOf(e.getMessage()).contains(\"for @typeHint deserialization\")) {\n        return objectMapper.convertValue(node, Map.class); // degrade gracefully\n    }\n    throw e;\n}","preventionTips":["Share state model classes via a common module across services","Pin identical spring-ai-alibaba versions on all nodes exchanging state","Audit checkpoints for @typeHint values after dependency upgrades","Prefer interface-based state fields with stable, always-present implementations"],"tags":["deserialization","classnotfound","jackson","classpath","type-hint"],"backgroundTag":"class-not-found","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}