NationalSecurityAgency/ghidra · error · IllegalArgumentException

Address-selection column must have Address, AddressRange, or

Error message

Address-selection column must have Address, AddressRange, or AddressSetView type

What it means

Thrown by the DefaultEnumeratedColumnProgramTableModel constructor when the designated selection column (selColumn) has a value class that is not Address, AddressRange, or AddressSetView. The selection column drives getProgramSelection(), which only knows how to assemble an AddressSet from those three types, so any other column type would silently break program selection.

Source

Thrown at Ghidra/Debug/ProposedUtils/src/main/java/docking/widgets/table/DefaultEnumeratedColumnProgramTableModel.java:39

import ghidra.program.util.ProgramLocation;
import ghidra.program.util.ProgramSelection;

public class DefaultEnumeratedColumnProgramTableModel<C extends Enum<C> & EnumeratedTableColumn<C, R>, R>
		extends DefaultEnumeratedColumnTableModel<C, R>
		implements EnumeratedColumnProgramTableModel<R> {
	protected final C selColumn;

	private Program program;

	public DefaultEnumeratedColumnProgramTableModel(PluginTool tool, String name, Class<C> colType,
			C selColumn) {
		super(tool, name, colType);
		if (selColumn != null) {
			Class<?> valueClass = selColumn.getValueClass();
			if (!Address.class.isAssignableFrom(valueClass) &&
				!AddressRange.class.isAssignableFrom(valueClass) &&
				!AddressSetView.class.isAssignableFrom(valueClass)) {
				throw new IllegalArgumentException(
					"Address-selection column must have Address, AddressRange, " +
						"or AddressSetView type");
			}
		}
		this.selColumn = selColumn;
	}

	@Override
	public ProgramLocation getProgramLocation(int row, int column) {
		Class<?> columnClass = getColumnClass(column);
		if (!Address.class.isAssignableFrom(columnClass) &&
			!ProgramLocation.class.isAssignableFrom(columnClass)) {
			return null;
		}
		Object value = getValueAt(row, column);
		if (value instanceof Address) {
			return new ProgramLocation(program, (Address) value);
		}

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Point selColumn at the enum constant whose getValueClass() returns Address, AddressRange, or AddressSetView.
  2. If no such column exists, pass selColumn=null to disable program selection entirely.
  3. Add or designate an address-producing column in the enum and give it a getValueOf that returns an Address/AddressRange/AddressSetView.

Example fix

// before
new DefaultEnumeratedColumnProgramTableModel<>(
    tool, "MyTable", MyCol.class, MyCol.NAME); // NAME.getValueClass() == String

// after
new DefaultEnumeratedColumnProgramTableModel<>(
    tool, "MyTable", MyCol.class, MyCol.ADDRESS); // ADDRESS.getValueClass() == Address
Defensive patterns

Strategy: validation

Validate before calling

Class<?> vc = selColumn != null ? selColumn.getValueClass() : null;
boolean ok = selColumn == null ||
    Address.class.isAssignableFrom(vc) ||
    AddressRange.class.isAssignableFrom(vc) ||
    AddressSetView.class.isAssignableFrom(vc);
if (!ok) selColumn = null; // or pick the address column
new DefaultEnumeratedColumnProgramTableModel<>(tool, name, colType, selColumn);

Prevention

When it happens

Trigger: Passing a selColumn enum constant whose getValueClass() returns String, Integer, Boolean, or any custom type. Designating a display-only column (e.g. a name or size column) as the selection column. Using the same enum for both data display and selection when the value class is not address-oriented.

Common situations: New table model subclasses that copy an existing constructor call and point selColumn at the wrong enum constant. Reusing an enumerated column that previously held addresses but was changed to hold a label or scalar type. Passing selColumn by index/ordinal confusion.

Related errors


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