spring-projects/spring-framework · error · IllegalStateException

Failed to bind all argument names

Error message

Failed to bind all argument names: {} argument(s) could not be bound

What it means

Thrown by AspectJAdviceParameterNameDiscoverer.getParameterNames (line 270-273) after the full 7-step binding algorithm (join point, throwing, annotation, returning, primitive args, this/target/args, reference pointcut) has run and numberOfRemainingUnboundArguments is still > 0. Every heuristic was exhausted and some parameters could not be assigned a name, so binding cannot complete. Only raised when raiseExceptions is true (which AbstractAspectJAdvice sets at line 461).

Solutions

  1. Compile with -parameters so DefaultParameterNameDiscoverer can supply names before this discoverer runs.
  2. Add a binding form to the pointcut (args(x), this(x), target(x), @annotation(x)) for each remaining parameter.
  3. Explicitly specify arg-names so the discoverer is bypassed.
  4. Remove parameters the pointcut cannot bind.

Example fix

// before — pointcut binds nothing, advice has an unbindable param, no -parameters
@After("execution(* svc.*(..))")
public void after(JoinPoint jp, Object mystery) { ... }

// after — bind 'mystery' via args() or name it explicitly
@After("execution(* svc.*(..)) && args(mystery)")
public void after(JoinPoint jp, Object mystery) { ... }
Defensive patterns

Strategy: validation

Validate before calling

import org.springframework.core.DefaultParameterNameDiscoverer;
import java.lang.reflect.Method;

// Pre-flight: confirm parameter names are discoverable OR pointcut binds all params.
boolean bindingWillSucceed(Method adviceMethod, String pointcutExpr) {
    String[] names = new DefaultParameterNameDiscoverer().getParameterNames(adviceMethod);
    return names != null; // simplest reliable pre-check; else ensure pointcut binds everything
}

Type guard

boolean namesAvailableOrFullyBound(Method m, String pointcutExpr) {
    return new org.springframework.core.DefaultParameterNameDiscoverer().getParameterNames(m) != null
        || pointcutExpr.matches(".*(args|this|target|@annotation|@args)\\(.*\\).*");
}

Try / catch

try {
    advice.getPointcut();
} catch (IllegalStateException ex) {
    if (ex.getMessage().contains("could not be bound")) {
        // add a binding form to the pointcut or compile with -parameters, then retry
    } else { throw ex; }
}

Prevention

When it happens

Trigger: An advice method has a parameter that none of the heuristics can name: it is not a JoinPoint/StaticPart, not a Throwable (when throwing set), not an Annotation (when @annotation set), not a primitive (when args() set), and not matchable via this()/target()/args()/reference pointcut. Typically a method with an extra parameter that the pointcut expression does not account for.

Common situations: Adding a parameter to an advice method that the pointcut does not bind, compiling without -parameters so names are unavailable, or using a pointcut expression with no bindable forms. Common when migrating from annotation-driven binding to pure pointcut-string binding.

Related errors


AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09). Data as JSON: /api/errors/cc035866de8e80ed. Report an issue: GitHub.

Appendix: source

Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/AspectJAdviceParameterNameDiscoverer.java:271

					default -> throw new IllegalStateException("Unknown algorithmic step: " + (algorithmicStep - 1));
				}
			}
		}
		catch (AmbiguousBindingException | IllegalArgumentException ex) {
			if (this.raiseExceptions) {
				throw ex;
			}
			else {
				return null;
			}
		}

		if (this.numberOfRemainingUnboundArguments == 0) {
			return this.parameterNameBindings;
		}
		else {
			if (this.raiseExceptions) {
				throw new IllegalStateException("Failed to bind all argument names: " +
						this.numberOfRemainingUnboundArguments + " argument(s) could not be bound");
			}
			else {
				// convention for failing is to return null, allowing participation in a chain of responsibility
				return null;
			}
		}
	}

	/**
	 * An advice method can never be a constructor in Spring.
	 * @return {@code null}
	 * @throws UnsupportedOperationException if
	 * {@link #setRaiseExceptions(boolean) raiseExceptions} has been set to {@code true}
	 */
	@Override
	public String @Nullable [] getParameterNames(Constructor<?> ctor) {
		if (this.raiseExceptions) {

View on GitHub (pinned to 69bf83ad71)