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
- Call builder.setInterceptor(MyInterceptor.class) (or the factory variant) before build()
- If the interceptor is conditional, ensure both branches configure either the interceptor or a factory
- 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
- Always set interceptor or factory immediately after creating the builder
- Unit-test plugin transform methods with a builder that mimics the real flow
- Never conditionally skip interceptor setup without also setting a factory
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
- method not found.
- must return java.lang.Object.
- BracketMatcherOperator is not an operation target.
- bytecode read fail path
- define fail Caused by
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)