bazelbuild/bazel · error · IllegalArgumentException
Class %s has multiple methods named getAssociatedTypeConstru
Error message
Class %s has multiple methods named getAssociatedTypeConstructor
What it means
CallUtils.getAssociatedTypeConstructor scans a class's declared methods for 'getAssociatedTypeConstructor' to find its fixed Starlark type constructor. If more than one declared method carries that name (regardless of signature), the lookup is ambiguous and this IllegalArgumentException is thrown.
Source
Thrown at src/main/java/net/starlark/java/eval/CallUtils.java:454
* getAssociatedTypeConstructor()} static method, or null if it does not have such a method.
*
* @throws IllegalArgumentException if the method exists but has an unexpected signature, or if it
* does not evaluate successfully
*/
@Nullable
private static TypeConstructor getAssociatedTypeConstructor(Class<?> clazz) {
// Special-case bool, which is represented by Java booleans and does not have its own class.
// (String.class does not need special-casing because it's already been replaced by
// StringModule.class by this point.)
if (clazz.equals(Boolean.class) || clazz.equals(boolean.class)) {
return Types.BOOL_CONSTRUCTOR;
}
Method found = null;
for (Method m : clazz.getDeclaredMethods()) {
if (m.getName().equals("getAssociatedTypeConstructor")) {
if (found != null) {
throw new IllegalArgumentException(
String.format(
"Class %s has multiple methods named getAssociatedTypeConstructor",
clazz.getName()));
}
found = m;
}
}
if (found == null) {
return null;
}
// Signature check.
if (!Modifier.isPublic(found.getModifiers())
|| !Modifier.isStatic(found.getModifiers())
|| !found.getReturnType().equals(TypeConstructor.class)
|| found.getParameterCount() != 0) {
throw new IllegalArgumentException(
String.format(View on GitHub (pinned to e6e199d060)
Solutions
- Keep a single declared method named getAssociatedTypeConstructor.
- Rename helper/overload variants to different names.
- Delete dead private variants left by refactors.
Example fix
// before
class T {
public static TypeConstructor getAssociatedTypeConstructor() {...}
private static TypeConstructor getAssociatedTypeConstructor(boolean legacy) {...}
}
// after
class T {
public static TypeConstructor getAssociatedTypeConstructor() {...}
private static TypeConstructor legacyTypeConstructor(boolean legacy) {...}
} Defensive patterns
Strategy: validation
Validate before calling
// Assert a single declared accessor before registration
static void checkSingleAccessor(Class<?> c) {
int n = 0;
for (Method m : c.getDeclaredMethods()) if (m.getName().equals("getAssociatedTypeConstructor")) n++;
if (n > 1) throw new IllegalArgumentException(c + " declares " + n + " accessors");
} Prevention
- Reserve the exact name getAssociatedTypeConstructor for the accessor only.
- Name helpers differently during refactors.
- Review merges for duplicated accessor methods.
When it happens
Trigger: Declaring both `static TypeConstructor getAssociatedTypeConstructor()` and an overloaded `getAssociatedTypeConstructor(Object o)` on the same class; keeping a private helper with the same name as the public accessor.
Common situations: Copy-pasting the accessor pattern and leaving the original; refactoring that introduces an overload; multiple people adding the hook in a merge.
Related errors
- Method %s#getAssociatedTypeConstructor has an invalid signat
- Expected one of %s and %s to be a subclass of the other
- Error invoking %s#getAssociatedTypeConstructor
- No member %s of the %s annotation found for element.
- Class %s has an incompatible overload of annotated method %s
AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14).
Data as JSON: /api/errors/3206cad552cc0f94.
Report an issue: GitHub.