theonedev/onedev · error · ExplicitException

Property 'type' is reserved (class: <className>)

Error message

Property 'type' is reserved (class: <className>)

What it means

During YAML data migration, VersionedYamlDoc builds a property set from a class's @Editable getters and setters. A bean property named 'type' is disallowed because 'type' is used internally in the versioned YAML document format to record the class name. Any persistable class exposing a getter/setter pair named 'type' aborts the migration/deserialization with this ExplicitException.

Source

Thrown at server-core/src/main/java/io/onedev/server/data/migration/VersionedYamlDoc.java:232

			        }
			    }

			};
			representer.setDefaultFlowStyle(FlowStyle.BLOCK);
			representer.setPropertyUtils(new PropertyUtils() {

				@Override
				protected Set<Property> createPropertySet(Class<? extends Object> type, BeanAccess bAccess) {
					List<Property> properties = new ArrayList<>();
					Map<String, Integer> orders = new HashMap<>();
					if (type.getAnnotation(Editable.class) != null) {
						for (Method getter: BeanUtils.findGetters(type)) {
							Editable editable = getter.getAnnotation(Editable.class);
							Method setter = BeanUtils.findSetter(getter);
							if (editable != null && setter != null) {
								String propertyName = BeanUtils.getPropertyName(getter);
								if (propertyName.equals("type"))
									throw new ExplicitException("Property 'type' is reserved (class: " + type.getName() + ")");
								try {
									properties.add(new MethodProperty(new PropertyDescriptor(propertyName, getter, setter)));
								} catch (IntrospectionException e) {
									throw new RuntimeException(e);
								}
								orders.put(propertyName, editable.order());
							}
						}
					}
					Collections.sort(properties, new Comparator<Property>() {

						@Override
						public int compare(Property o1, Property o2) {
							return orders.get(o1.getName()) - orders.get(o2.getName());
						}
						
					});
					return new LinkedHashSet<>(properties);

View on GitHub (pinned to d44925c47c)

Solutions

  1. Rename the bean property from 'type' to something else (e.g. 'typeName' or 'itemType').
  2. If 'type' must not be persisted, remove it from the bean or drop the @Editable annotation / setter so it is excluded from the property set.
  3. If the field is required for new data, add a migration step converting old YAML docs that used 'type'.
  4. Check whether the bean is actually meant to participate in versioned YAML persistence; exclude it if not.

Example fix

// before
@Editable
public String getType() { return type; }
public void setType(String type) { this.type = type; }
// after
@Editable
public String getItemType() { return itemType; }
public void setItemType(String itemType) { this.itemType = itemType; }
Defensive patterns

Strategy: validation

Validate before calling

for (Method getter : BeanUtils.findGetters(type)) {
    if (BeanUtils.getPropertyName(getter).equals("type"))
        throw new IllegalStateException(type.getName() + " must not define a bean property named 'type'");
}

Type guard

boolean hasReservedTypeProperty(Class<?> type) {
    return BeanUtils.findGetters(type).stream()
        .anyMatch(g -> BeanUtils.getPropertyName(g).equals("type"));
}

Try / catch

try {
    doc.createPropertySet();
} catch (ExplicitException e) {
    log.error("Bean violates versioned YAML constraints: " + e.getMessage());
    throw new ConfigurationException(e.getMessage());
}

Prevention

When it happens

Trigger: Persisting (via versioned YAML) a class that has an @Editable getter named getType() with a matching setter; e.g. adding a field named 'type' to a data entity or migration DTO.

Common situations: Renaming an enum-like discriminator field to 'type' on a persisted entity; copying POJO patterns from other frameworks where 'type' is a natural field name; old migrations failing after a new field was introduced.

Related errors


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