bazelbuild/bazel · error · IllegalStateException
Class %s has an incompatible overload of annotated method %s
Error message
Class %s has an incompatible overload of annotated method %s declared by %s
What it means
While collecting @StarlarkMethod annotations along a class hierarchy, StarlarkAnnotations found a method in a subclass with the same name and parameter count as an inherited annotated method, but a parameter type is not assignable — i.e. a genuine (not erased/generic-compatible) overload of an annotated method. Overloading annotated Starlark methods this way is unsupported, so an IllegalStateException is thrown at descriptor-build time.
Source
Thrown at src/main/java/net/starlark/java/annot/StarlarkAnnotations.java:225
// invariants should be verified in annotation processor or in test, and left out of this
// method.
Method[] methods = classObj.getDeclaredMethods();
Class<?>[] paramsToMatch = signatureToMatch.getParameterTypes();
StarlarkMethod callable = null;
for (Method method : methods) {
if (signatureToMatch.getName().equals(method.getName())
&& method.isAnnotationPresent(StarlarkMethod.class)) {
Class<?>[] paramTypes = method.getParameterTypes();
if (paramTypes.length == paramsToMatch.length) {
for (int i = 0; i < paramTypes.length; i++) {
// This verifies assignability of the method signature to ensure this is not a
// coincidental overload. We verify assignability instead of matching exact parameter
// classes in order to match generic methods.
if (!paramTypes[i].isAssignableFrom(paramsToMatch[i])) {
throw new IllegalStateException(
String.format(
"Class %s has an incompatible overload of annotated method %s declared by %s",
classObj, signatureToMatch.getName(), signatureToMatch.getDeclaringClass()));
}
}
}
if (callable == null) {
callable = method.getAnnotation(StarlarkMethod.class);
} else {
throw new IllegalStateException(
String.format(
"Class %s has multiple overloaded methods named '%s' annotated "
+ "with @StarlarkMethod",
classObj, signatureToMatch.getName()));
}
}
}
return callable;View on GitHub (pinned to e6e199d060)
Solutions
- Make the subclass override use identical (or assignable-to-super) parameter types.
- Rename the subclass method if it is meant to be a distinct operation, not an override.
- Remove @StarlarkMethod from the accidental overload.
- If a different signature is required, expose it under a different Starlark method name via structType/name attribute.
Example fix
// before
class Base { @StarlarkMethod(name="merge") public void m(Dict<?,?> d) {} }
class Sub extends Base {
@StarlarkMethod(name="merge") public void m(Sequence<?> s) {} // incompatible overload
}
// after
class Sub extends Base {
@StarlarkMethod(name="merge_seq") public void m(Sequence<?> s) {} // distinct name
} Defensive patterns
Strategy: validation
Validate before calling
// In a build-time test, assert no incompatible annotated overloads exist
static void checkNoIncompatibleOverloads(Class<?> c) {
for (Method m : c.getDeclaredMethods()) {
if (!m.isAnnotationPresent(StarlarkMethod.class)) continue;
for (Method sup : c.getSuperclass().getMethods()) {
if (sup.getName().equals(m.getName())
&& sup.isAnnotationPresent(StarlarkMethod.class)
&& sup.getParameterCount() == m.getParameterCount()) {
for (int i = 0; i < m.getParameterCount(); i++)
if (!m.getParameterTypes()[i].isAssignableFrom(sup.getParameterTypes()[i]))
throw new AssertionError(m + ' incompatible with inherited ' + sup);
}
}
}
} Prevention
- When overriding an exported method, copy the exact parameter types from the base declaration.
- Give genuinely different operations different Starlark names.
- Add a reflection-based consistency test for Starlark-exposed classes.
When it happens
Trigger: Subclass declares void m(OtherType x) with @StarlarkMethod while superclass has @StarlarkMethod void m(MyType x); the assignability check paramTypes[i].isAssignableFrom(paramsToMatch[i]) fails for some parameter.
Common situations: Refactoring an exported Starlark method's parameter type in a base class without updating subclasses; adding a convenience overload that coincidentally carries the annotation via copy-paste; generics erasure producing a bridge with incompatible raw types.
Related errors
- Class %s has multiple overloaded methods named '%s' annotate
- Expected one of %s and %s to be a subclass of the other
- Class %s has two selfCall methods defined
- Converter %s has %d methods 'convert(String, Object)', expec
- %s missing getStarlarkType(StarlarkSemantics) method
AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14).
Data as JSON: /api/errors/133c890f05c1712e.
Report an issue: GitHub.