{"record":{"id":"7730d6b7ab79ce2d","repo":"apple/pkl","slug":"vmtypemismatchexception-classtype-value-is-not-a","errorCode":null,"errorMessage":"VmTypeMismatchException.ClassType (value is not a subclass of the expected class)","messagePattern":"VmTypeMismatchException\\.ClassType \\(value is not a subclass of the expected class\\)","errorType":"exception","errorClass":"VmTypeMismatchException.ClassType","httpStatus":null,"severity":"error","filePath":"pkl-core/src/main/java/org/pkl/core/ast/type/TypeNode.java","lineNumber":3282,"sourceCode":"      // safe to init clazz here (instead of on init and typealias instantiate)\n      // because in the typealias case this node will never execute prior to instantiation\n      initVmClass();\n\n      // Fast path: all classes match Class<Any> / Class<unknown> / Class<type arg>.\n      // In this case, skip the subclass check and behave like a bare `Class` type annotation.\n      if (clazz == BaseModule.getAnyClass()) {\n        return value;\n      }\n\n      // clazz will be null iff the type arg is a not a valid class type\n      if (clazz == null) {\n        CompilerDirectives.transferToInterpreter();\n        throw new VmTypeMismatchException.ClassType(sourceSection, value, typeNode.doExport());\n      }\n\n      if (!value.isSubclassOf(clazz)) {\n        CompilerDirectives.transferToInterpreter();\n        throw new VmTypeMismatchException.ClassType(sourceSection, value, clazz);\n      }\n\n      return value;\n    }\n\n    @Fallback\n    protected Object fallback(Object value) {\n      throw typeMismatch(value, BaseModule.getClassClass());\n    }\n\n    @Override\n    protected boolean acceptTypeNode(boolean visitTypeArguments, TypeNodeConsumer consumer) {\n      if (visitTypeArguments) {\n        return consumer.accept(this) && typeNode.acceptTypeNode(visitTypeArguments, consumer);\n      }\n      return consumer.accept(this);\n    }\n","sourceCodeStart":3264,"sourceCodeEnd":3300,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-core/src/main/java/org/pkl/core/ast/type/TypeNode.java#L3264-L3300","documentation":"ClassClassTypeNode validates that a `Class` value (a Pkl class object) is a subclass of the class expected by the `Class<T>` type argument. When value.isSubclassOf(clazz) fails, it throws VmTypeMismatchException.ClassType reporting the expected class.","triggerScenarios":"A `Class<T>` annotation (e.g. `Class<Animal>`) receives a class object that is not T or a subclass of T (e.g. the class object `Unrelated`), or a sibling class at the same level.","commonSituations":"Factory/registry patterns that pass class objects around (`elementClass: Class<...>`); changing a class hierarchy so a previously-passing class object no longer derives from T; typos selecting the wrong class.","solutions":["Pass a class object that is T or a subclass of T.","Widen the type argument to a common superclass (or `Any`) if unrelated classes must be accepted.","Check the expected class named in the error and verify the hierarchy with `isSubclassOf`."],"exampleFix":"// before\nelemClass: Class<Animal> = Robot\n// after (Robot is not an Animal)\nelemClass: Class<Any> = Robot","handlingStrategy":"validation","validationCode":"// Pkl: check subclass relation before passing a class object\nfunction checkClass(c: Class): Boolean = c.isSubclassOf(Animal)","typeGuard":"value is Class && value.isSubclassOf(Animal)","tryCatchPattern":null,"preventionTips":["Verify class hierarchies with isSubclassOf before passing class objects.","Widen Class<T> arguments to a common superclass when multiple hierarchies are involved.","Keep hierarchy refactors covered by pkl test fixtures."],"tags":["pkl","type-mismatch","subclass"],"backgroundTag":"type-mismatch","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}