NationalSecurityAgency/ghidra · error · NotFoundException

Block model not found: " + modelName

Error message

Block model not found: " + modelName

What it means

Thrown by BlockModelServicePlugin.getNewModelByName() when the requested modelName is not found in either the basic-models map or the subroutine-models map. Both maps are case-sensitive TreeMaps populated in the plugin constructor with a fixed set of names plus any dynamically registered via registerModel(). The fixed names are: 'Simple Block' (basic), and 'Multiple Entry', 'Overlapped Code', 'Isolated Entry', 'Partitioned Code' (subroutine).

Source

Thrown at Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/blockmodel/BlockModelServicePlugin.java:414

	/**
	 * @see ghidra.app.services.BlockModelService#getNewModelByName(java.lang.String, ghidra.program.model.listing.Program, boolean)
	 */
	@Override
	public CodeBlockModel getNewModelByName(String modelName, Program program,
			boolean includeExternals) throws NotFoundException {
		if (program == null) {
			return null;
		}
		BlockModelInfo info = basicModelsByName.get(modelName);
		if (info != null) {
			return getModelInstance(info.modelClass, program, includeExternals);
		}
		info = subroutineModelsByName.get(modelName);
		if (info != null) {
			return getModelInstance(info.modelClass, program, includeExternals);
		}
		throw new NotFoundException("Block model not found: " + modelName);
	}

	/**
	 * @see ghidra.app.services.BlockModelService#getAvailableModelNames(int)
	 */
	@Override
	public String[] getAvailableModelNames(int modelType) {

		TreeMap<String, BlockModelInfo> models =
			(modelType == BASIC_MODEL) ? basicModelsByName : subroutineModelsByName;
		String defaultModelName =
			(modelType == BASIC_MODEL) ? DEFAULT_BLOCK_MODEL_NAME : DEFAULT_SUBROUTINE_MODEL_NAME;

		ArrayList<String> list = new ArrayList<>();
		for (String modelName : models.keySet()) {
			if (modelName.equals(defaultModelName)) {
				list.add(0, modelName);
			}

View on GitHub (pinned to d5f144c24d)

Solutions

  1. List the valid names first: Arrays.toString(service.getAvailableModelNames(BlockModelService.ANY_BLOCK)) and use an exact, case-correct value from that list.
  2. Reference the NAME constant of the model class instead of a string literal, e.g. SimpleBlockModel.NAME ("Simple Block") or MultEntSubModel.NAME ("Multiple Entry").
  3. If you only need a working model, prefer getActiveBlockModel(program) / getActiveSubroutineModel(program) which never throw NotFoundException.
  4. If a custom model is required, register it with service.registerModel(modelClass, modelName) before requesting it by name.

Example fix

// before - hardcoded, wrong-case literal
CodeBlockModel m = service.getNewModelByName("simple block", program);
// -> NotFoundException: Block model not found: simple block

// after - use the registered NAME constant (exact, case-correct)
CodeBlockModel m = service.getNewModelByName(SimpleBlockModel.NAME, program);
// or guard by listing available names:
String[] names = service.getAvailableModelNames(BlockModelService.BASIC_MODEL);
CodeBlockModel m = java.util.Arrays.asList(names).contains(modelName)
    ? service.getNewModelByName(modelName, program)
    : service.getActiveBlockModel(program);
Defensive patterns

Strategy: validation

Validate before calling

// Validate modelName against the service's own list before requesting it.
import ghidra.app.services.BlockModelService;
String[] basic = service.getAvailableModelNames(BlockModelService.BASIC_MODEL);
String[] sub   = service.getAvailableModelNames(BlockModelService.SUBROUTINE_MODEL);
java.util.Set<String> valid = new java.util.HashSet<>();
java.util.Collections.addAll(valid, basic);
java.util.Collections.addAll(valid, sub);
if (!valid.contains(modelName)) {
    // pick the active model instead of throwing
    return service.getActiveBlockModel(program);
}
return service.getNewModelByName(modelName, program);

Try / catch

// Recommended: validate first (see validationCode). If you must call
// directly, narrow the catch and fall back to the active model.
try {
    return service.getNewModelByName(modelName, program);
} catch (ghidra.util.exception.NotFoundException e) {
    // modelName unknown; degrade to active model rather than crashing.
    // Do NOT loop/retry the same name.
    return service.getActiveBlockModel(program);
}

Prevention

When it happens

Trigger: Calling blockModelService.getNewModelByName(modelName, program, ...) with a name that is misspelled, has wrong case (the maps are case-sensitive), or is not among the registered models. Also when a previously-registered model has been unregistered via unregisterModel().

Common situations: Hardcoded model name from an older or newer Ghidra version where a constant changed; using a class name or display label instead of the registered model NAME constant (e.g. passing "SimpleBlockModel" instead of "Simple Block"); case mismatch such as "simple block" vs "Simple Block"; calling before a dynamically-registered model exists.

Related errors


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