projectlombok/lombok · error · ClassCastException

Not an annotation type

Error message

Not an annotation type: <target>

What it means

SpiLoadUtil.findAnnotationHelper resolves an annotation class from a service-loader config value, which may be a Class or a Field. If the resolved target is neither null nor a Class assignable to java.lang.annotation.Annotation, it throws this ClassCastException. It means the configured type is not an annotation type as required.

Solutions

  1. Check the configured value at <target>: it must be the fully-qualified name of an @interface (annotation type), not a class or enum.
  2. Fix the FQN in the service/config registration to reference the annotation itself (e.g. lombok.foo.HandlerAnnotation), not its processor.
  3. Verify the referenced type still extends java.lang.annotation.Annotation after refactors; update stale names.
  4. If the target may legitimately be absent, note that findAnnotationHelper returns null (not an exception) when the field value is null — only non-Class, non-Annotation values throw.

Example fix

// before (config value points at a class, not an annotation)
lombok.launch.AnnotationProcessorHider$AstModificationNotifier  -> ClassCastException
// after (point at the annotation type)
lombok.extern.java.Log
Defensive patterns

Strategy: validation

Validate before calling

Object target = ...; // resolved config value
if (target instanceof Class<?> c && !java.lang.annotation.Annotation.class.isAssignableFrom(c))
    throw new IllegalStateException("Configured type is not an annotation: " + c.getName());

Type guard

static boolean isAnnotationType(Object o) {
    return o instanceof Class<?> c && java.lang.annotation.Annotation.class.isAssignableFrom(c);
}

Try / catch

try {
    Class<? extends Annotation> ann = findAnnotationClass(field, loader);
} catch (ClassCastException e) {
    if (e.getMessage().startsWith("Not an annotation type:")) {
        // fix the FQN in the service config to point at the @interface
    } else throw e;
}

Prevention

When it happens

Trigger: findAnnotationClass -> findAnnotationHelper with a registration whose value is a Class that does not extend Annotation (e.g. a plain class, interface, or enum listed where an annotation is expected) — typical of a typo'd FQN in a service/annotation-map config or a class placed under the wrong registration key.

Common situations: Typing a handler class name where the annotation FQN should go; renaming/refactoring an annotation so the config still points at the old non-annotation class; registering the annotation's processor class instead of the annotation itself.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of projectlombok/lombok@6d6a3e9fec (2026-09-07). Data as JSON: /api/errors/2d0520c2391dcd66. Report an issue: GitHub.

Appendix: source

Thrown at src/utils/lombok/core/SpiLoadUtil.java:193

			if (potential != null) return potential;
		}
		
		return null;
	}
	
	@SuppressWarnings("unchecked")
	private static Class<? extends Annotation> findAnnotationHelper(Class<?> base, Type iface) {
		if (iface instanceof ParameterizedType) {
			ParameterizedType p = (ParameterizedType)iface;
			if (!base.equals(p.getRawType())) return null;
			Type target = p.getActualTypeArguments()[0];
			if (target instanceof Class<?>) {
				if (Annotation.class.isAssignableFrom((Class<?>) target)) {
					return (Class<? extends Annotation>) target;
				}
			}
			
			throw new ClassCastException("Not an annotation type: " + target);
		}
		return null;
	}
}

View on GitHub (pinned to 6d6a3e9fec)