{"record":{"id":"81dfc25c0dce2030","repo":"theonedev/onedev","slug":"unsupported-type-x","errorCode":null,"errorMessage":"Unsupported type: X","messagePattern":"Unsupported type: X","errorType":"exception","errorClass":"ExplicitException","httpStatus":null,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/ai/BuildSpecSchema.java","lineNumber":357,"sourceCode":"            var enumList = new ArrayList<String>();\n            var enumClass = (Class<Enum>) type;\n            for (var enumValue: EnumSet.allOf(enumClass)) {\n                enumList.add(((Enum) enumValue).name());\n            }\n            currentNode.put(\"enum\", enumList);\n        } else if (type == Date.class) {\n            currentNode.put(\"type\", \"string\");\n            currentNode.put(\"format\", \"date-time\");\n        } else if (type.getAnnotation(Editable.class) != null) {\n            if (ClassUtils.isConcrete(type)) {\n                currentNode.put(\"type\", \"object\");\n                processBean(currentNode, type, new ArrayList<>(), new HashSet<>());\n                currentNode.put(\"additionalProperties\", false);    \n            } else {\n                processPolymorphic(currentNode, type);\n            }\n        } else {\n            throw new ExplicitException(\"Unsupported type: \" + type);\n        }    \n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private static void processPolymorphic(Map<String, Object> currentNode, Class<?> baseClass) {\n        Collection<Class<?>> implementations = new ArrayList<>();\n        var implementationProvider = baseClass.getAnnotation(ImplementationProvider.class);\n        if (implementationProvider != null) \n            implementations.addAll((Collection<? extends Class<? extends Serializable>>) ReflectionUtils.invokeStaticMethod(baseClass, implementationProvider.value()));\n        else \n            implementations.addAll(OneDev.getInstance(ImplementationRegistry.class).getImplementations(baseClass));\n\n        currentNode.put(\"type\", \"object\");\n        \n        var propsNode = new HashMap<String, Object>();\n        var typeNode = new HashMap<String, Object>();\n        typeNode.put(\"type\", \"string\");\n        propsNode.put(\"type\", typeNode);","sourceCodeStart":339,"sourceCodeEnd":375,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/ai/BuildSpecSchema.java#L339-L375","documentation":"processType maps Java types to JSON schema nodes and supports only known categories (primitives, enums, strings, collections, beans, polymorphic hierarchies). Any other type reaches the final else branch and throws this ExplicitException.","triggerScenarios":"A build spec bean property (or collection element) has a return type that is not a supported primitive/String/enum/Date/Collection/bean subtype, e.g. an arbitrary class, Object, or an interface without known implementations, so processType throws.","commonSituations":"Custom spec classes exposing exotic types (InputStream, byte[], custom third-party types) as properties; forgetting to register implementations for a polymorphic base interface.","solutions":["Change the property type to a supported one (String, int, boolean, enum, Date, typed Collection, or a bean class extending a known hierarchy).","If the type is meant to be polymorphic, ensure it has discoverable implementations that processPolymorphic can enumerate (proper class hierarchy/interface registration).","Wrap unsupported types into a bean or serialize them as String in the spec class."],"exampleFix":"// before\npublic Object getOptions() {...}\n// after\npublic Map<String, String> getOptions() {...} // or a dedicated bean type","handlingStrategy":"type-guard","validationCode":"Class<?> t = getter.getReturnType();\nboolean supported = t.isPrimitive() || t == String.class || t.isEnum()\n    || Date.class.isAssignableFrom(t) || Collection.class.isAssignableFrom(t)\n    || isKnownBeanOrPolymorphic(t);\nif (!supported) throw new IllegalStateException(\"Unsupported spec type: \" + t);","typeGuard":"function isSupportedSpecType(Class<?> t) {\n  return t.isPrimitive() || t == String.class || t.isEnum()\n      || Collection.class.isAssignableFrom(t) || isKnownBeanOrPolymorphic(t);\n}","tryCatchPattern":"try {\n    schema = BuildSpecSchema.generate(specClass);\n} catch (ExplicitException e) {\n    if (e.getMessage().startsWith(\"Unsupported type:\")) {\n        // replace the property type named in the message with a supported one\n    }\n}","preventionTips":["Restrict spec bean properties to supported types.","Avoid Object or third-party types as property types.","Test schema generation for every new spec class."],"tags":["schema","types","buildspec","reflection"],"backgroundTag":"unsupported-operation","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}