pinpoint-apm/pinpoint · error · RuntimeException
${before} not allowed return. ${Arrays.toString(beforeParamL
Error message
${before} not allowed return. ${Arrays.toString(beforeParamList)} What it means
The before method was marked @IgnoreMethod (capturing skipped), yet it also has a TraceBlock return type. A block-type before method implies blocking interception around both phases, which is incompatible with ignoring the before capture, so the factory rejects this combination.
Source
Thrown at agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/interceptor/InterceptorDefinitionFactory.java:202
final boolean beforeIgnoreMethod = beforeMethod.isAnnotationPresent(IgnoreMethod.class);
final boolean blockType = beforeMethod.getReturnType() == TraceBlock.class;
final Method afterMethod = searchMethod(targetInterceptorClazz, after, afterParamList);
if (afterMethod == null) {
throw new RuntimeException(after + " method not found. " + Arrays.toString(afterParamList));
}
final boolean afterIgnoreMethod = afterMethod.isAnnotationPresent(IgnoreMethod.class);
if (interceptorType == InterceptorType.RESULT_REPLACE && afterMethod.getReturnType() != Object.class) {
// a covariant override would change the weaved call descriptor and break the INVOKEINTERFACE site.
throw new RuntimeException(after + " must return java.lang.Object. " + targetInterceptorClazz.getName());
}
if (beforeIgnoreMethod && afterIgnoreMethod) {
return new DefaultInterceptorDefinition(interceptorClazz, targetInterceptorClazz, interceptorType, CaptureType.NON, null, null);
}
if (beforeIgnoreMethod) {
if (blockType) {
throw new RuntimeException(before + " not allowed return. " + Arrays.toString(beforeParamList));
}
return new DefaultInterceptorDefinition(interceptorClazz, targetInterceptorClazz, interceptorType, CaptureType.AFTER, null, afterMethod);
}
if (afterIgnoreMethod) {
if (blockType) {
throw new RuntimeException(after + " not allowed return. " + Arrays.toString(afterParamList));
}
return new DefaultInterceptorDefinition(interceptorClazz, targetInterceptorClazz, interceptorType, CaptureType.BEFORE, beforeMethod, null);
}
if (blockType) {
return new DefaultInterceptorDefinition(interceptorClazz, targetInterceptorClazz, interceptorType, CaptureType.BLOCK_AROUND, beforeMethod, afterMethod);
}
return new DefaultInterceptorDefinition(interceptorClazz, targetInterceptorClazz, interceptorType, CaptureType.AROUND, beforeMethod, afterMethod);
}
private Method searchMethod(Class<?> interceptorClazz, String searchMethodName, Class<?>[] searchMethodParameter) {
Objects.requireNonNull(searchMethodName, "searchMethodName");View on GitHub (pinned to 744c3d3075)
Solutions
- Remove @IgnoreMethod from the block-type before method so CaptureType.BLOCK_AROUND is selected
- Or remove the TraceBlock return type if the intent is truly a BEFORE-skipped (after-only) interceptor
- Adjust the InterceptorType so the before/after combination matches the intended capture semantics
Example fix
// before
@IgnoreMethod public TraceBlock before(Object target, Object[] args) { ... }
// after
public TraceBlock before(Object target, Object[] args) { ... } Defensive patterns
Strategy: validation
Validate before calling
if (before.isAnnotationPresent(IgnoreMethod.class) && before.getReturnType() == TraceBlock.class) throw new IllegalStateException("IgnoreMethod + TraceBlock before not allowed"); Try / catch
try { def = factory.buildInterceptorDefinition(...); } catch (RuntimeException e) { log.error("invalid before/after ignore config: {}", e.getMessage()); throw e; } Prevention
- Never combine @IgnoreMethod with TraceBlock return types
- Decide capture semantics (BEFORE/AFTER/BLOCK_AROUND) before writing interceptor methods
- Mirror the built-in interceptor examples when choosing annotations
When it happens
Trigger: Defining an interceptor where the before method is annotated @IgnoreMethod AND returns TraceBlock, then building its InterceptorDefinition (CaptureType.AFTER path validation).
Common situations: Mixing 'skip before capture' optimization with TraceApiBlock-style blocking interceptor semantics in one interceptor class; copying @IgnoreMethod from an after method onto a block-type before method.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- ${after} not allowed return. ${Arrays.toString(afterParamLis
- not found interceptorHolderClass, className=
- not found interceptor, className=
- ${after} method not found. ${Arrays.toString(afterParamList)
- ${after} must return java.lang.Object. ${targetInterceptorCl
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/7ab4f6d98c8446cf.
Report an issue: GitHub.