{"record":{"id":"8120aa076f558cd9","repo":"spring-projects/spring-framework","slug":"proceedingjoinpoint-is-only-supported-for-around-a","errorCode":null,"errorMessage":"ProceedingJoinPoint is only supported for around advice","messagePattern":"ProceedingJoinPoint is only supported for around advice","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java","lineNumber":408,"sourceCode":"\t\t}\n\n\t\tthis.argumentsIntrospected = true;\n\t}\n\n\tprivate boolean maybeBindJoinPoint(Class<?> candidateParameterType) {\n\t\tif (JoinPoint.class == candidateParameterType) {\n\t\t\tthis.joinPointArgumentIndex = 0;\n\t\t\treturn true;\n\t\t}\n\t\telse {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tprivate boolean maybeBindProceedingJoinPoint(Class<?> candidateParameterType) {\n\t\tif (ProceedingJoinPoint.class == candidateParameterType) {\n\t\t\tif (!supportsProceedingJoinPoint()) {\n\t\t\t\tthrow new IllegalArgumentException(\"ProceedingJoinPoint is only supported for around advice\");\n\t\t\t}\n\t\t\tthis.joinPointArgumentIndex = 0;\n\t\t\treturn true;\n\t\t}\n\t\telse {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tprotected boolean supportsProceedingJoinPoint() {\n\t\treturn false;\n\t}\n\n\tprivate boolean maybeBindJoinPointStaticPart(Class<?> candidateParameterType) {\n\t\tif (JoinPoint.StaticPart.class == candidateParameterType) {\n\t\t\tthis.joinPointStaticPartArgumentIndex = 0;\n\t\t\treturn true;\n\t\t}","sourceCodeStart":390,"sourceCodeEnd":426,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-aop/src/main/java/org/springframework/aop/aspectj/AbstractAspectJAdvice.java#L390-L426","documentation":"Thrown by maybeBindProceedingJoinPoint (line 405-416) when an advice method declares a parameter of type ProceedingJoinPoint but supportsProceedingJoinPoint() returns false. The base class returns false (line 418-420); only AspectJAroundAdvice overrides it to true. ProceedingJoinPoint.proceed() requires the ability to resume the target invocation, which only around advice can offer.","triggerScenarios":"Declaring a ProceedingJoinPoint parameter on a @Before, @After, @AfterReturning, or @AfterThrowing method, or an <aop:before>/<aop:after> element whose method takes org.aspectj.lang.ProceedingJoinPoint. Also when programmatically constructing AspectJMethodBeforeAdvice for a method that uses ProceedingJoinPoint.","commonSituations":"Changing an @Around advice to @Before/@After and forgetting to change the parameter type from ProceedingJoinPoint to JoinPoint. Copy-pasting an around-advice signature into a non-around advice. XML where method='before' but the method signature expects a ProceedingJoinPoint.","solutions":["Change the advice annotation/element to @Around / <aop:around> so supportsProceedingJoinPoint() is true.","Or change the parameter type from ProceedingJoinPoint to JoinPoint (for before/after/afterReturning/afterThrowing).","If you need to proceed, you must use around advice — there is no workaround."],"exampleFix":"// before — ProceedingJoinPoint on a non-around advice\n@Before(\"execution(* svc.*(..))\")\npublic void check(ProceedingJoinPoint pjp) { /* cannot proceed */ }\n\n// after — either use @Around with proceed(), or @Before with JoinPoint\n@Around(\"execution(* svc.*(..))\")\npublic Object check(ProceedingJoinPoint pjp) throws Throwable { return pjp.proceed(); }","handlingStrategy":"type-guard","validationCode":"import org.aspectj.lang.ProceedingJoinPoint;\nimport java.lang.reflect.Method;\n\n// Reject non-around advice that declares a ProceedingJoinPoint parameter.\nvoid assertNoProceedingJoinPointUnlessAround(Method adviceMethod, boolean isAround) {\n    if (!isAround && adviceMethod.getParameterCount() > 0\n            && adviceMethod.getParameterTypes()[0] == ProceedingJoinPoint.class) {\n        throw new IllegalArgumentException(\n            \"ProceedingJoinPoint requires around advice: \" + adviceMethod);\n    }\n}","typeGuard":"boolean usesProceedingJoinPoint(Method m) {\n    return m.getParameterCount() > 0\n        && m.getParameterTypes()[0] == org.aspectj.lang.ProceedingJoinPoint.class;\n}","tryCatchPattern":"try {\n    advice.calculateArgumentBindings();\n} catch (IllegalArgumentException ex) {\n    if (ex.getMessage().contains(\"ProceedingJoinPoint\")) {\n        // switch the advice to @Around, or change the param to JoinPoint\n    } else { throw ex; }\n}","preventionTips":["Use ProceedingJoinPoint only in @Around advice; use JoinPoint elsewhere.","When converting @Around to another advice type, also change the parameter type.","Add a CI check that scans advice methods for ProceedingJoinPoint misuse."],"tags":["spring-aop","aspectj","around-advice","proceeding-join-point","advice-type"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}