NationalSecurityAgency/ghidra · error · IllegalArgumentException

editor class must have accessible default constructor

Error message

editor class must have accessible default constructor

What it means

Thrown by AutoOptions.registerOptionsDefined() when the PropertyEditor class specified in an @AutoOptionDefined(editor=...) annotation cannot be instantiated via a public no-arg constructor. The framework reflectively calls getConstructor().newInstance(), so editors must be instantiable with zero arguments. This is skipped in headless mode (where editors are not used).

Source

Thrown at Ghidra/Debug/ProposedUtils/src/main/java/ghidra/framework/options/AutoOptions.java:161

			if (type == OptionType.NO_TYPE) {
				throw new IllegalArgumentException(
					"Could not determine option type from default value: " + f + " = " +
						defaultValue);
			}

			String description = annotation.description();
			Class<? extends PropertyEditor> editorClass = annotation.editor();
			final PropertyEditor editor;
			if (editorClass == PropertyEditor.class || SystemUtilities.isInHeadlessMode()) {
				editor = null;
			}
			else {
				try {
					editor = editorClass.getConstructor().newInstance();
				}
				catch (InstantiationException | IllegalAccessException | IllegalArgumentException
						| InvocationTargetException | NoSuchMethodException | SecurityException e) {
					throw new IllegalArgumentException(
						"editor class must have accessible default constructor", e);
				}
			}

			if (defaultValue instanceof GColor gColor) {
				options.registerThemeColorBinding(key.name, gColor.getId(), help, description);
			}
			/*
			else if ( is font option ) {
			
				// Note: there is no font value to check against for fonts in the new Theme system.
				// If annotation fonts are needed, then they should be bound by String id.  Likely,
				// annotation fonts are not needed now that have themes.  We also probably no
				// longer need annotation colors either.
			
				options.registerThemeFontBinding(description, fontId, help, description);
			}
			*/

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Add a public no-arg constructor to the editor class.
  2. Ensure editor() references a concrete (non-abstract) class.
  3. If the editor needs configuration, initialize it lazily via a property setter rather than constructor args.
  4. Omit editor() (defaults to PropertyEditor.class) if a custom editor is not required.

Example fix

// before
public class MyEditor extends PropertyEditorSupport {
  public MyEditor(String config) { ... } // only non-default ctor
}
@AutoOptionDefined(editor = MyEditor.class, ...)

// after
public class MyEditor extends PropertyEditorSupport {
  public MyEditor() { this("default"); }
  public MyEditor(String config) { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

Class<? extends PropertyEditor> ec = annotation.editor();
if (ec != PropertyEditor.class && !SystemUtilities.isInHeadlessMode()) {
  try { ec.getConstructor(); }
  catch (NoSuchMethodException nsme) {
    throw new IllegalStateException("Editor " + ec + " lacks a public no-arg ctor");
  }
}

Prevention

When it happens

Trigger: Specifying an editor class with no default constructor, a private no-arg constructor, an abstract editor class, or a class that throws from its constructor. In headless mode the check is bypassed, so this only fires in GUI mode.

Common situations: Reusing a third-party PropertyEditor that requires constructor arguments; marking the no-arg constructor private for encapsulation; passing an interface or abstract class as the editor; an editor whose initializer needs resources unavailable in GUI mode.

Related errors


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