spring-projects/spring-framework · error · IllegalStateException

Value annotation must have a value attribute

Error message

Value annotation must have a value attribute

What it means

Thrown by QualifierAnnotationAutowireCandidateResolver.extractValue() when a value-annotation (used for @Value-style expression resolution) is found but has no attribute named 'value'. Spring's suggested-value resolution looks for a 'value' attribute on the annotation (configured via setValueAnnotationType, defaults to Value.class). If the annotation lacks this attribute, the resolver cannot extract the expression string.

Solutions

  1. Ensure the custom value annotation type declares a 'value' attribute (the conventional name Spring expects).
  2. If using @Value (the default), verify it is from the correct package (org.springframework.beans.factory.annotation.Value) which has the value attribute.
  3. If your annotation uses a different attribute name, override findValue()/extractValue() in a subclass to extract from the correct attribute.

Example fix

// before
// Custom annotation without 'value' attribute
@Retention(RetentionPolicy.RUNTIME)
public @interface MyValue {
    String expression(); // wrong attribute name
}

// after
@Retention(RetentionPolicy.RUNTIME)
public @interface MyValue {
    String value(); // matches what Spring expects
}
Defensive patterns

Strategy: validation

Validate before calling

// Verify the value annotation type has a 'value' attribute
Class<? extends Annotation> valueAnnotationType = MyValue.class;
try {
    valueAnnotationType.getDeclaredMethod("value");
    // 'value' attribute exists — safe to use
} catch (NoSuchMethodException e) {
    throw new IllegalStateException(
        valueAnnotationType + " must declare a 'value' attribute");
}

Type guard

// Type guard: check that an annotation type has a 'value' attribute
static boolean hasValueAttribute(Class<? extends Annotation> type) {
    try {
        type.getDeclaredMethod("value");
        return true;
    } catch (NoSuchMethodException e) {
        return false;
    }
}

Prevention

When it happens

Trigger: Configuring a custom value annotation type (via setValueAnnotationType) that does not declare a 'value' attribute. The findValue() method at line 425-433 successfully finds merged annotation attributes for the value annotation type, but extractValue() finds no 'value' key in the attributes.

Common situations: Setting a custom annotation as the valueAnnotationType that has attributes named differently (e.g., 'expression' instead of 'value'). Subclassing QualifierAnnotationAutowireCandidateResolver and overriding setValueAnnotationType with a non-standard annotation. Framework integration where a custom value annotation lacks the conventional 'value' attribute.

Related errors


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

Appendix: source

Thrown at spring-beans/src/main/java/org/springframework/beans/factory/annotation/QualifierAnnotationAutowireCandidateResolver.java:443

	protected @Nullable Object findValue(Annotation[] annotationsToSearch) {
		if (annotationsToSearch.length > 0) {   // qualifier annotations have to be local
			AnnotationAttributes attr = AnnotatedElementUtils.getMergedAnnotationAttributes(
					AnnotatedElementUtils.forAnnotations(annotationsToSearch), this.valueAnnotationType);
			if (attr != null) {
				return extractValue(attr);
			}
		}
		return null;
	}

	/**
	 * Extract the value attribute from the given annotation.
	 * @since 4.3
	 */
	protected Object extractValue(AnnotationAttributes attr) {
		Object value = attr.get(AnnotationUtils.VALUE);
		if (value == null) {
			throw new IllegalStateException("Value annotation must have a value attribute");
		}
		return value;
	}

}

View on GitHub (pinned to 69bf83ad71)