bumptech/glide · error · IllegalArgumentException

RequestOptionsExtensions must be public, with private constr

Error message

RequestOptionsExtensions must be public, with private constructors and only static methods. Found a non-private constructor in: {}

What it means

A @GlideExtension is a pure container of static methods, so its constructors must be private to prevent instantiation. validateExtensionConstructor rejects any constructor whose modifiers do not include PRIVATE. The enclosing class name is included so you can locate the offending constructor.

Source

Thrown at annotation/compiler/src/main/java/com/bumptech/glide/annotation/compiler/GlideExtensionValidator.java:82

      }
    }
  }

  private static String getQualifiedMethodName(ExecutableElement executableElement) {
    return getEnclosingClassName(executableElement) + "#" + getName(executableElement);
  }

  private static String getEnclosingClassName(Element element) {
    return element.getEnclosingElement().toString();
  }

  private static String getName(Element element) {
    return element.toString();
  }

  private static void validateExtensionConstructor(Element element) {
    if (!element.getModifiers().contains(Modifier.PRIVATE)) {
      throw new IllegalArgumentException(
          "RequestOptionsExtensions must be public, with private constructors and only static"
              + " methods. Found a non-private constructor in: "
              + getEnclosingClassName(element));
    }
    ExecutableElement executableElement = (ExecutableElement) element;
    if (!executableElement.getParameters().isEmpty()) {
      throw new IllegalArgumentException(
          "RequestOptionsExtensions must be public, with private constructors and only static"
              + " methods. Found parameters in the constructor of: "
              + getEnclosingClassName(element));
    }
  }

  private void validateGlideOption(ExecutableElement executableElement) {
    validateGlideOptionAnnotations(executableElement);
    validateGlideOptionParameters(executableElement);
    TypeMirror returnType = executableElement.getReturnType();
    if (!isBaseRequestOptions(returnType)) {

View on GitHub (pinned to eb14a895d8)

Solutions

  1. Add an explicit private no-arg constructor to the @GlideExtension class.
  2. In Kotlin use `class MyGlideExtension private constructor()`.
  3. Remove any additional non-private constructors; only private constructors are allowed.

Example fix

// before
@GlideExtension
public class MyGlideExtension {
  // implicit public no-arg constructor -> rejected
  @GlideOption public static RequestOptions cache(RequestOptions o) { ... }
}

// after
@GlideExtension
public class MyGlideExtension {
  private MyGlideExtension() {}
  @GlideOption public static RequestOptions cache(RequestOptions o) { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

@Test void glideExtensionConstructorsArePrivate() {
  for (java.lang.reflect.Constructor<?> c : MyGlideExtension.class.getDeclaredConstructors()) {
    assertTrue("constructor must be private: " + c, java.lang.reflect.Modifier.isPrivate(c.getModifiers()));
  }
}

Prevention

When it happens

Trigger: GlideExtensionValidator.validateExtensionConstructor fires for each ElementKind.CONSTRUCTOR inside a @GlideExtension class; throws when `!element.getModifiers().contains(Modifier.PRIVATE)`. Hit by a class with an implicit public no-arg constructor (no explicit private constructor) or an explicitly package-private/protected/public constructor.

Common situations: Forgetting to add a private constructor to a utility-style extension class (Java inserts a default public one); Kotlin `class` without an explicit `private constructor()`; copying a normal utility class and adding @GlideExtension without privatizing the constructor.

Related errors


AI-assisted analysis of bumptech/glide@eb14a895d8 (2026-08-14). Data as JSON: /api/errors/aaba61524672d24f. Report an issue: GitHub.