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

  1. Keep a single declared method named getAssociatedTypeConstructor.
  2. Rename helper/overload variants to different names.
  3. 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

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


AI-assisted analysis of bazelbuild/bazel@e6e199d060 (2026-08-14). Data as JSON: /api/errors/3206cad552cc0f94. Report an issue: GitHub.