pinpoint-apm/pinpoint · error · InstrumentException

either interceptor or interceptorFactory must be present.

Error message

either interceptor or interceptorFactory must be present.

What it means

InstrumentException thrown by ASMInterceptorHolder.Builder.build when neither an interceptor class nor an interceptor factory was supplied before building the interceptor holder. The builder requires one of the two to know how to initialize the holder, so it fails fast instead of producing a broken interceptor.

Solutions

  1. Call builder.setInterceptor(MyInterceptor.class) (or the factory variant) before build()
  2. If the interceptor is conditional, ensure both branches configure either the interceptor or a factory
  3. Add an assertion/log before build() to confirm interceptor configuration is present

Example fix

// before
return newBuilder().interceptMethod(method).build();
// after
return newBuilder().interceptMethod(method).interceptor(MyInterceptor.class).build();
Defensive patterns

Strategy: validation

Validate before calling

Objects.requireNonNull(interceptorClass, "interceptorClass"); // or interceptorFactory
builder.interceptor(interceptorClass).build();

Type guard

boolean readyForBuild(Builder b) { return b.hasInterceptor() || b.hasInterceptorFactory(); }

Try / catch

try {
    return builder.build();
} catch (InstrumentException e) {
    if (e.getMessage().contains("interceptor or interceptorFactory")) {
        logger.error("plugin interceptor not configured", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling build() on a builder where neither setInterceptor(Class) nor setInterceptorFactory(...) was invoked; a plugin passing null/omitting the interceptor registration call in its instrumentation code.

Common situations: Plugin authors forgetting to call setInterceptor after setInterceptables; conditional code paths that skip interceptor setup; refactoring a plugin and accidentally dropping the interceptor setter call.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07). Data as JSON: /api/errors/61ad90b7cffb4aaa. Report an issue: GitHub.

Appendix: source

Thrown at agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/ASMInterceptorHolder.java:244

            final int interceptorId = interceptorHolderIdGenerator.getId();
            final ASMInterceptorHolder holder = new ASMInterceptorHolder(interceptorId);
            final Class<?> clazz;
            if (classLoader == null || isReflectionDelegatingClassLoader(classLoader)) {
                // define into the bootstrap classloader, eagerly create the interceptor
                clazz = holder.defineClass(null);
                if (interceptor == null && interceptorFactory != null) {
                    interceptor = interceptorFactory.newInterceptor(interceptorClass, providedArguments, scopeInfo, methodDescriptor);
                }
            } else {
                clazz = holder.defineClass(classLoader);
            }
            // exception handling.
            if (interceptor != null) {
                holder.init(clazz, interceptor);
            } else if (interceptorFactory != null) {
                holder.init(clazz, interceptorFactory, interceptorClass, providedArguments, scopeInfo, methodDescriptor);
            } else {
                throw new InstrumentException("either interceptor or interceptorFactory must be present.");
            }

            return holder;
        }
    }

    static class RenameClassAdapter extends ClassVisitor {
        private final String newInternalName;

        public RenameClassAdapter(ClassVisitor classVisitor, String name) {
            super(ASMVersion.VERSION, classVisitor);
            this.newInternalName = JavaAssistUtils.javaNameToJvmName(name);
        }

        @Override
        public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
            super.visit(version, access, this.newInternalName, signature, superName, interfaces);
        }

View on GitHub (pinned to 744c3d3075)