theonedev/onedev · error · ExplicitException

Unsupported type: X

Error message

Unsupported type: X

What it means

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.

Source

Thrown at server-core/src/main/java/io/onedev/server/ai/BuildSpecSchema.java:357

            var enumList = new ArrayList<String>();
            var enumClass = (Class<Enum>) type;
            for (var enumValue: EnumSet.allOf(enumClass)) {
                enumList.add(((Enum) enumValue).name());
            }
            currentNode.put("enum", enumList);
        } else if (type == Date.class) {
            currentNode.put("type", "string");
            currentNode.put("format", "date-time");
        } else if (type.getAnnotation(Editable.class) != null) {
            if (ClassUtils.isConcrete(type)) {
                currentNode.put("type", "object");
                processBean(currentNode, type, new ArrayList<>(), new HashSet<>());
                currentNode.put("additionalProperties", false);    
            } else {
                processPolymorphic(currentNode, type);
            }
        } else {
            throw new ExplicitException("Unsupported type: " + type);
        }    
    }

    @SuppressWarnings("unchecked")
    private static void processPolymorphic(Map<String, Object> currentNode, Class<?> baseClass) {
        Collection<Class<?>> implementations = new ArrayList<>();
        var implementationProvider = baseClass.getAnnotation(ImplementationProvider.class);
        if (implementationProvider != null) 
            implementations.addAll((Collection<? extends Class<? extends Serializable>>) ReflectionUtils.invokeStaticMethod(baseClass, implementationProvider.value()));
        else 
            implementations.addAll(OneDev.getInstance(ImplementationRegistry.class).getImplementations(baseClass));

        currentNode.put("type", "object");
        
        var propsNode = new HashMap<String, Object>();
        var typeNode = new HashMap<String, Object>();
        typeNode.put("type", "string");
        propsNode.put("type", typeNode);

View on GitHub (pinned to d44925c47c)

Solutions

  1. Change the property type to a supported one (String, int, boolean, enum, Date, typed Collection, or a bean class extending a known hierarchy).
  2. If the type is meant to be polymorphic, ensure it has discoverable implementations that processPolymorphic can enumerate (proper class hierarchy/interface registration).
  3. Wrap unsupported types into a bean or serialize them as String in the spec class.

Example fix

// before
public Object getOptions() {...}
// after
public Map<String, String> getOptions() {...} // or a dedicated bean type
Defensive patterns

Strategy: type-guard

Validate before calling

Class<?> t = getter.getReturnType();
boolean supported = t.isPrimitive() || t == String.class || t.isEnum()
    || Date.class.isAssignableFrom(t) || Collection.class.isAssignableFrom(t)
    || isKnownBeanOrPolymorphic(t);
if (!supported) throw new IllegalStateException("Unsupported spec type: " + t);

Type guard

function isSupportedSpecType(Class<?> t) {
  return t.isPrimitive() || t == String.class || t.isEnum()
      || Collection.class.isAssignableFrom(t) || isKnownBeanOrPolymorphic(t);
}

Try / catch

try {
    schema = BuildSpecSchema.generate(specClass);
} catch (ExplicitException e) {
    if (e.getMessage().startsWith("Unsupported type:")) {
        // replace the property type named in the message with a supported one
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: Custom spec classes exposing exotic types (InputStream, byte[], custom third-party types) as properties; forgetting to register implementations for a polymorphic base interface.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/81dfc25c0dce2030. Report an issue: GitHub.