pinpoint-apm/pinpoint · warning

Skip adding interceptor. 'already intercepted method' class=

Error message

Skip adding interceptor. 'already intercepted method' class={}, interceptor={}

What it means

ASMMethod.addInterceptor0 logs this and returns without throwing when the target method's ASM method node already has an interceptor attached. Pinpoint allows only one interceptor per method per weave, so a second addInterceptor/addScopedInterceptor request on the same method is silently skipped. It protects the transformed class from double-probing.

Source

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

        final ScopeFactory scopeFactory = this.engineComponent.getScopeFactory();
        final ScopeInfo scopeInfo = scopeFactory.newScopeInfo(pluginContext, interceptorClass, interceptorScope, executionPolicy);
        return createInterceptor(interceptorClass, constructorArgs, scopeInfo);
    }

    private ASMInterceptorHolder createInterceptor(Class<? extends Interceptor> interceptorClass, Object[] constructorArgs, ScopeInfo scopeInfo) throws InstrumentException {
        final ObjectBinderFactory objectBinderFactory = this.engineComponent.getObjectBinderFactory();
        final AnnotatedInterceptorFactory factory = objectBinderFactory.newAnnotatedInterceptorFactory(this.pluginContext);
        final InterceptorHolderIdGenerator interceptorHolderIdGenerator = engineComponent.getInterceptorHolderIdGenerator();
        return ASMInterceptorHolder.create(interceptorHolderIdGenerator, declaringClass.getClassLoader(), factory, interceptorClass, constructorArgs, scopeInfo, descriptor);
    }

    private void addInterceptor0(Class<? extends Interceptor> interceptorClass, ASMInterceptorHolder interceptorHolder) throws InstrumentException {
        Objects.requireNonNull(interceptorClass, "interceptorClass");

        final InterceptorDefinition interceptorDefinition = this.engineComponent.createInterceptorDefinition(interceptorClass);
        final CaptureType captureType = interceptorDefinition.getCaptureType();
        if (this.methodNode.hasInterceptor()) {
            logger.warn("Skip adding interceptor. 'already intercepted method' class={}, interceptor={}", this.declaringClass.getName(), interceptorClass.getName());
            return;
        }

        if (this.methodNode.isAbstract() || this.methodNode.isNative()) {
            logger.info("Skip adding interceptor. 'abstract or native method' class={}, interceptor={}", this.declaringClass.getName(), interceptorClass.getName());
            return;
        }

        int apiId = 0;
        final InterceptorType interceptorType = interceptorDefinition.getInterceptorType();
        if (interceptorType == InterceptorType.API_ID_AWARE || interceptorType == InterceptorType.ASYNC_CONTEXT_API_ID_AWARE) {
            apiId = this.engineComponent.cacheApi(this.descriptor);
        }

        if (interceptorType == InterceptorType.RESULT_REPLACE && !this.methodNode.hasObjectOrArrayReturnType()) {
            // constructors and void/primitive returns have no reference return value to replace.
            throw new InstrumentException("result-replace interceptor requires an object or array return type."
                    + " class=" + this.declaringClass.getName() + ", method=" + this.methodNode.getName() + this.methodNode.getDesc()

View on GitHub (pinned to 744c3d3075)

Solutions

  1. Check which interceptor was applied first; remove the duplicate registration or narrow the matching pointcut so only one interceptor targets the method.
  2. If chaining is intended, use a scoped interceptor design that delegates instead of two independent interceptors on one method.
  3. Verify plugins are not double-loaded (same plugin jar present twice in the plugin directory).
  4. Treat this as an expected warn if a base profile already instrumented the method.

Example fix

// before
method.addScopedInterceptor( MyInterceptor.class, "myTraceScope" );
// after
if (!methodInfo.isIntercepted()) { // or ensure only one plugin registers this API
    method.addScopedInterceptor( MyInterceptor.class, "myTraceScope" );
}
Defensive patterns

Strategy: validation

Validate before calling

if (methodNode.hasInterceptor()) {
    logger.info("method already instrumented, skipping {}", methodName);
    return;
}

Try / catch

try { method.addScopedInterceptor(cls, scope); } catch (InstrumentException e) { log.warn("interceptor add failed for {}", methodName, e); }

Prevention

When it happens

Trigger: Calling addInterceptor/addScopedInterceptor/addInterceptorInternal on a method that a previous interceptor (or another plugin/profile targeting the same method) has already instrumented; two plugins matching the same method; agent re-transform hitting an already-woven class.

Common situations: Overlapping service-type/plugin configurations where both match the same API; duplicate interceptor registration in custom plugins; re-attaching the agent or applying a transform twice to the same class.

Related errors


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