NationalSecurityAgency/ghidra · warning · UnsupportedOperationException

headless use not supported

Error message

headless use not supported

What it means

Thrown by FindDataTypeConflictCauseScript.run when state.getTool() returns null, i.e. the script is executed in headless mode. The script needs the GUI PluginTool to obtain the DataTypeManagerService and the user's currently selected datatype, neither of which exists without a headed tool.

Source

Thrown at Ghidra/Features/Base/ghidra_scripts/FindDataTypeConflictCauseScript.java:43

import ghidra.framework.plugintool.PluginTool;
import ghidra.program.database.data.DataTypeUtilities;
import ghidra.program.model.data.*;
import ghidra.program.model.data.Enum;

public class FindDataTypeConflictCauseScript extends GhidraScript {

	private DataTypeManager dtm;
	private HashSet<Integer> previouslyDetectedPairHashes;
	private boolean hasReport;

	@Override
	protected void run() throws Exception {

		previouslyDetectedPairHashes = new HashSet<>();

		PluginTool tool = state.getTool();
		if (tool == null) {
			throw new UnsupportedOperationException("headless use not supported");
		}

		DataTypeManagerService dtmService = tool.getService(DataTypeManagerService.class);
		if (dtmService == null) {
			popup("Tool does not contain a DataTypeManagerService!");
			return;
		}

		List<DataType> selectedDatatypes = dtmService.getSelectedDatatypes();
		if (selectedDatatypes.size() != 1) {
			popup("Select a single conflict datatype before running script");
			return;
		}

		DataType selectedDt = DataTypeUtilities.getBaseDataType(selectedDatatypes.get(0));
		if (selectedDt == null) {
			popup("Selected datatype must not be a default Pointer");
			return;

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Run FindDataTypeConflictCauseScript inside the GUI CodeBrowser tool, not headless.
  2. If you need headless conflict analysis, write a custom script that iterates datatypes directly via the program's DataTypeManager instead of relying on the service.
  3. Check `state.getTool() != null` before calling and exit gracefully with a message.

Example fix

// before
PluginTool tool = state.getTool();
if (tool == null) {
    throw new UnsupportedOperationException("headless use not supported");
}

// after
PluginTool tool = state.getTool();
if (tool == null) {
    println("This script requires the GUI CodeBrowser tool.");
    return;
}
Defensive patterns

Strategy: validation

Validate before calling

PluginTool tool = state.getTool();
if (tool == null) {
    println("FindDataTypeConflictCauseScript requires the GUI tool.");
    return;
}

Type guard

boolean isHeadless(GhidraScript script) {
    return script.getState().getTool() == null;
}

Try / catch

try {
    run();
} catch (UnsupportedOperationException e) {
    if (e.getMessage().equals("headless use not supported")) {
        println("Run inside the CodeBrowser GUI tool.");
    } else throw e;
}

Prevention

When it happens

Trigger: Invoking FindDataTypeConflictCauseScript via analyzeHeadless, the headless analyzer, or any non-GHG script environment where there is no PluginTool. Also if run from a context where the script state was constructed without a tool.

Common situations: Trying to batch-run this interactive diagnostic in a headless pipeline. Running from a script that constructs GhidraScript state manually without a tool. Misconfiguring a headless script runner.

Related errors


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