{"record":{"id":"7ab4f6d98c8446cf","repo":"pinpoint-apm/pinpoint","slug":"before-not-allowed-return-arrays-tostring-be","errorCode":null,"errorMessage":"${before} not allowed return. ${Arrays.toString(beforeParamList)}","messagePattern":"(.+?) not allowed return\\. (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/interceptor/InterceptorDefinitionFactory.java","lineNumber":202,"sourceCode":"            final boolean beforeIgnoreMethod = beforeMethod.isAnnotationPresent(IgnoreMethod.class);\n            final boolean blockType = beforeMethod.getReturnType() == TraceBlock.class;\n            final Method afterMethod = searchMethod(targetInterceptorClazz, after, afterParamList);\n            if (afterMethod == null) {\n                throw new RuntimeException(after + \" method not found. \" + Arrays.toString(afterParamList));\n            }\n            final boolean afterIgnoreMethod = afterMethod.isAnnotationPresent(IgnoreMethod.class);\n\n            if (interceptorType == InterceptorType.RESULT_REPLACE && afterMethod.getReturnType() != Object.class) {\n                // a covariant override would change the weaved call descriptor and break the INVOKEINTERFACE site.\n                throw new RuntimeException(after + \" must return java.lang.Object. \" + targetInterceptorClazz.getName());\n            }\n\n            if (beforeIgnoreMethod && afterIgnoreMethod) {\n                return new DefaultInterceptorDefinition(interceptorClazz, targetInterceptorClazz, interceptorType, CaptureType.NON, null, null);\n            }\n            if (beforeIgnoreMethod) {\n                if (blockType) {\n                    throw new RuntimeException(before + \" not allowed return. \" + Arrays.toString(beforeParamList));\n                }\n                return new DefaultInterceptorDefinition(interceptorClazz, targetInterceptorClazz, interceptorType, CaptureType.AFTER, null, afterMethod);\n            }\n            if (afterIgnoreMethod) {\n                if (blockType) {\n                    throw new RuntimeException(after + \" not allowed return. \" + Arrays.toString(afterParamList));\n                }\n                return new DefaultInterceptorDefinition(interceptorClazz, targetInterceptorClazz, interceptorType, CaptureType.BEFORE, beforeMethod, null);\n            }\n            if (blockType) {\n                return new DefaultInterceptorDefinition(interceptorClazz, targetInterceptorClazz, interceptorType, CaptureType.BLOCK_AROUND, beforeMethod, afterMethod);\n            }\n\n            return new DefaultInterceptorDefinition(interceptorClazz, targetInterceptorClazz, interceptorType, CaptureType.AROUND, beforeMethod, afterMethod);\n        }\n\n        private Method searchMethod(Class<?> interceptorClazz, String searchMethodName, Class<?>[] searchMethodParameter) {\n            Objects.requireNonNull(searchMethodName, \"searchMethodName\");","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/pinpoint-apm/pinpoint/blob/744c3d3075e595656abb1ae331ad2c0e4c9eb996/agent-module/profiler/src/main/java/com/navercorp/pinpoint/profiler/instrument/interceptor/InterceptorDefinitionFactory.java#L184-L220","documentation":"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.","triggerScenarios":"Defining an interceptor where the before method is annotated @IgnoreMethod AND returns TraceBlock, then building its InterceptorDefinition (CaptureType.AFTER path validation).","commonSituations":"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.","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"],"exampleFix":"// before\n@IgnoreMethod public TraceBlock before(Object target, Object[] args) { ... }\n// after\npublic TraceBlock before(Object target, Object[] args) { ... }","handlingStrategy":"validation","validationCode":"if (before.isAnnotationPresent(IgnoreMethod.class) && before.getReturnType() == TraceBlock.class) throw new IllegalStateException(\"IgnoreMethod + TraceBlock before not allowed\");","typeGuard":null,"tryCatchPattern":"try { def = factory.buildInterceptorDefinition(...); } catch (RuntimeException e) { log.error(\"invalid before/after ignore config: {}\", e.getMessage()); throw e; }","preventionTips":["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"],"tags":["java","interceptor","ignore-method","traceblock","invalid-combination"],"backgroundTag":"invalid-argument-value","analyzedSha":"744c3d3075e595656abb1ae331ad2c0e4c9eb996","analyzedAt":"2026-09-07T18:48:45.289Z","contentChangedAt":"2026-09-07T18:48:45.289Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}