NationalSecurityAgency/ghidra · error · IllegalArgumentException

{}-annotated method {} cannot have more than two parameters

Error message

{}-annotated method {} cannot have more than two parameters

What it means

Thrown by AutoOptionsListener.MethodOptionSetter when an @AutoOptionConsumed-annotated method declares more than two parameters. The framework only supports zero, one (new or old value), or two (old+new) parameters; a larger arity has no defined value mapping and is rejected at setter-construction time.

Source

Thrown at Ghidra/Debug/ProposedUtils/src/main/java/ghidra/framework/options/AutoOptionsListener.java:157

				}
				else if (parameters[0].getAnnotation(OldValue.class) != null) {
					if (parameters[1].getAnnotation(OldValue.class) != null) {
						throw new IllegalArgumentException("Cannot apply " +
							OldValue.class.getName() + " to both parameters of " + method);
					}
					this.order = ParamOrder.OLD_NEW;
				}
				else {
					if (parameters[1].getAnnotation(NewValue.class) != null) {
						this.order = ParamOrder.OLD_NEW;
					}
					else {
						this.order = ParamOrder.NEW_OLD;
					}
				}
			}
			else {
				throw new IllegalArgumentException(AutoOptionConsumed.class + "-annotated method " +
					method + " cannot have more than two parameters");
			}
		}

		@Override
		public void set(R receiver, Object newValue, Object oldValue) {
			Object[] args = order.populate(oldValue, newValue);
			try {
				method.invoke(receiver, args);
			}
			catch (IllegalArgumentException | IllegalAccessException e) {
				String argsStr = StringUtils.join(args, ",");
				// Don't throw, so other consumers get updated
				Msg.error(this,
					"Could not invoke " + method + "(" + argsStr + ") for option " + key, e);
			}
			catch (InvocationTargetException e) {
				Throwable cause = e.getCause();

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Reduce the method to 0, 1, or 2 parameters, using only old/new value slots.
  2. Move extra context into a field on the receiver or obtain it inside the method body.
  3. Split logic across a minimal @AutoOptionConsumed method that delegates to a helper with more args.

Example fix

// before
@AutoOptionConsumed("my.opt")
void onChange(PluginTool tool, int newVal, int oldVal) { ... } // 3 params

// after
@AutoOptionConsumed("my.opt")
void onChange(@NewValue int newVal, @OldValue int oldVal) {
  doChange(this.tool, newVal, oldVal);
}
Defensive patterns

Strategy: validation

Validate before calling

int n = method.getParameterCount();
if (n > 2) {
  throw new IllegalStateException(
    "@AutoOptionConsumed method must have 0-2 params: " + method);
}

Prevention

When it happens

Trigger: An @AutoOptionConsumed method with three or more parameters, e.g. void onChange(String name, int newVal, int oldVal). Adding auxiliary parameters (a context or source) beyond the old/new pair.

Common situations: Refactoring a handler to take extra context arguments; copy-pasting a method signature from elsewhere without trimming to the supported arity; misunderstanding the supported parameter shapes.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/ea7e15c54ca60dd0. Report an issue: GitHub.