spring-projects/spring-framework · error · IllegalArgumentException

Either requiredType or propertyPath is required

Error message

Either requiredType or propertyPath is required

What it means

IllegalArgumentException from PropertyEditorRegistrySupport.registerCustomEditor when both requiredType and propertyPath are null. A custom editor must be scoped either by target type or by a specific property path; registering one with neither dimension is meaningless and rejected.

Solutions

  1. Pass the target type: registerCustomEditor(MyType.class, null, editor).
  2. Or pass the property path: registerCustomEditor(null, "bean.prop", editor).
  3. Prefer the two-argument overload registerCustomEditor(MyType.class, editor) when scoping by type.

Example fix

// before
registry.registerCustomEditor(null, null, new MyEditor());

// after
registry.registerCustomEditor(MyType.class, null, new MyEditor());
Defensive patterns

Strategy: validation

Validate before calling

// Validate before registering an editor
if (requiredType == null && propertyPath == null) {
    throw new IllegalArgumentException("Supply requiredType or propertyPath");
}
registry.registerCustomEditor(requiredType, propertyPath, editor);

Prevention

When it happens

Trigger: Calling registry.registerCustomEditor(null, null, myEditor) — the (Class, String, PropertyEditor) overload with both leading arguments null. Happens in custom ConfigurableBeanFactory setups or tests that build editors programmatically.

Common situations: Misunderstanding the overload resolution (calling registerCustomEditor(null, editor) is allowed, but registerCustomEditor(null, null, editor) is not); passing null defensively; copy-paste from a generic editor registration helper.

Related errors


AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09). Data as JSON: /api/errors/a8c651aff3e28fbc. Report an issue: GitHub.

Appendix: source

Thrown at spring-beans/src/main/java/org/springframework/beans/PropertyEditorRegistrySupport.java:308

		target.configValueEditorsActive = this.configValueEditorsActive;
		target.defaultEditors = this.defaultEditors;
		target.overriddenDefaultEditors = this.overriddenDefaultEditors;
	}


	//---------------------------------------------------------------------
	// Management of custom editors
	//---------------------------------------------------------------------

	@Override
	public void registerCustomEditor(Class<?> requiredType, PropertyEditor propertyEditor) {
		registerCustomEditor(requiredType, null, propertyEditor);
	}

	@Override
	public void registerCustomEditor(@Nullable Class<?> requiredType, @Nullable String propertyPath, PropertyEditor propertyEditor) {
		if (requiredType == null && propertyPath == null) {
			throw new IllegalArgumentException("Either requiredType or propertyPath is required");
		}
		if (propertyPath != null) {
			if (this.customEditorsForPath == null) {
				this.customEditorsForPath = new LinkedHashMap<>(16);
			}
			this.customEditorsForPath.put(propertyPath, new CustomEditorHolder(propertyEditor, requiredType));
		}
		else {
			if (this.customEditors == null) {
				this.customEditors = new LinkedHashMap<>(16);
			}
			this.customEditors.put(requiredType, propertyEditor);
			this.customEditorCache = null;
		}
	}

	@Override
	public @Nullable PropertyEditor findCustomEditor(@Nullable Class<?> requiredType, @Nullable String propertyPath) {

View on GitHub (pinned to 69bf83ad71)