clojure/clojure · error · UnsupportedOperationException

Module requires ASM6

Error message

Module requires ASM6

What it means

Modules (module-info classes, Java 9+) require the ASM6 visitor API. ClassVisitor.visitModule throws UnsupportedOperationException when the visitor's api is below Opcodes.ASM6 and a module is being visited.

Solutions

  1. Pass Opcodes.ASM6 or later to the ClassVisitor super constructor
  2. Upgrade the ASM dependency to a version supporting modules
  3. Skip module-info.class files in classpath scanners
  4. Handle UnsupportedOperationException as a signal to upgrade tooling

Example fix

// before
super(Opcodes.ASM5);
// after
super(Opcodes.ASM6);
Defensive patterns

Strategy: try-catch

Validate before calling

if (visitorApi < Opcodes.ASM6) { throw new IllegalStateException("Module support requires ASM6+ visitor"); }

Try / catch

try { visitor.visitModule(name, access, version); } catch (UnsupportedOperationException e) { log.warn("Visitor too old for modules, skipping module-info"); }

Prevention

When it happens

Trigger: Parsing a module-info.class or any class visit that triggers visitModule with a visitor built with api < Opcodes.ASM6 (ASM4/ASM5).

Common situations: Scanning a JDK 9+ application that uses the module system with legacy ASM-based tooling; annotation processors or agents built against ASM5 encountering module-info.class on the classpath.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of clojure/clojure@f3b143341d (2026-09-09). Data as JSON: /api/errors/01a3192f993ac1c4. Report an issue: GitHub.

Appendix: source

Thrown at src/jvm/clojure/asm/ClassVisitor.java:153

  public void visitSource(final String source, final String debug) {
    if (cv != null) {
      cv.visitSource(source, debug);
    }
  }

  /**
   * Visit the module corresponding to the class.
   *
   * @param name the fully qualified name (using dots) of the module.
   * @param access the module access flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC} and {@code
   *     ACC_MANDATED}.
   * @param version the module version, or {@literal null}.
   * @return a visitor to visit the module values, or {@literal null} if this visitor is not
   *     interested in visiting this module.
   */
  public ModuleVisitor visitModule(final String name, final int access, final String version) {
    if (api < Opcodes.ASM6) {
      throw new UnsupportedOperationException("Module requires ASM6");
    }
    if (cv != null) {
      return cv.visitModule(name, access, version);
    }
    return null;
  }

  /**
   * Visits the nest host class of the class. A nest is a set of classes of the same package that
   * share access to their private members. One of these classes, called the host, lists the other
   * members of the nest, which in turn should link to the host of their nest. This method must be
   * called only once and only if the visited class is a non-host member of a nest. A class is
   * implicitly its own nest, so it's invalid to call this method with the visited class name as
   * argument.
   *
   * @param nestHost the internal name of the host class of the nest (see {@link
   *     Type#getInternalName()}).
   */

View on GitHub (pinned to f3b143341d)