spring-projects/spring-security · error · AnnotationConfigurationException

Unsupported element of type

Error message

Unsupported element of type {element.getClass()}

What it means

UniqueSecurityAnnotationScanner.merge supports only Class and Method elements; for any other AnnotatedElement type it throws AnnotationConfigurationException, since a classpath/annotation-configuration problem is implied. It enforces that exactly one matching security annotation exists on the element.

Solutions

  1. Only call merge with Class or Method elements
  2. Filter the element type before invoking the scanner
  3. Provide a custom scanner implementation if other element types must be supported

Example fix

// before
return scanner.merge(element, targetClass); // element may be a Field
// after
if (element instanceof Class || element instanceof Method) {
    return scanner.merge(element, targetClass);
}
return null;
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(element instanceof Class) && !(element instanceof Method)) { return null; }

Type guard

boolean isSupportedElement(AnnotatedElement e) { return e instanceof Class || e instanceof Method; }

Prevention

When it happens

Trigger: Passing a Field/Constructor/Parameter (anything not Class or Method) to the scanner's merge, e.g. from a custom metadata source scanning other reflective element kinds.

Common situations: Custom security annotation scanning setups; framework hooks that iterate over all AnnotatedElements of a type instead of just classes and methods.

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 spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/ca2e42d81fe56b67. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/springframework/security/core/annotation/UniqueSecurityAnnotationScanner.java:127

		Assert.notNull(types, "types cannot be null");
		this.types = types;
	}

	@Override
	MergedAnnotation<A> merge(AnnotatedElement element, @Nullable Class<?> targetClass) {
		if (element instanceof Parameter parameter) {
			return this.uniqueParameterAnnotationCache.computeIfAbsent(parameter, (p) -> {
				List<MergedAnnotation<A>> annotations = findParameterAnnotations(p);
				return requireUnique(p, annotations);
			});
		}
		if (element instanceof Method method) {
			return this.uniqueMethodAnnotationCache.computeIfAbsent(new MethodClassKey(method, targetClass), (k) -> {
				List<MergedAnnotation<A>> annotations = findMethodAnnotations(method, targetClass);
				return requireUnique(method, annotations);
			});
		}
		throw new AnnotationConfigurationException("Unsupported element of type " + element.getClass());
	}

	private @Nullable MergedAnnotation<A> requireUnique(AnnotatedElement element,
			List<MergedAnnotation<A>> annotations) {
		return switch (annotations.size()) {
			case 0 -> null;
			case 1 -> annotations.get(0);
			default -> {
				List<Annotation> synthesized = new ArrayList<>();
				for (MergedAnnotation<A> annotation : annotations) {
					synthesized.add(annotation.synthesize());
				}
				throw new AnnotationConfigurationException("""
						Please ensure there is one unique annotation of type %s attributed to %s. \
						Found %d competing annotations: %s""".formatted(this.types, element, annotations.size(),
						synthesized));
			}
		};

View on GitHub (pinned to 96852e8860)