NationalSecurityAgency/ghidra · warning · InvalidInputException
Didn't remove external library {libName} since it isn't empt
Error message
Didn't remove external library {libName} since it isn't empty. What it means
Thrown by ExternalProgramMerger.removeExternalLibrary when an external library still has external locations referencing it. The merger's policy is to only remove empty libraries; iter.hasNext() returning true means at least one ExternalLocation remains, so removal is aborted and InvalidInputException is raised. This protects against orphaning external location references during a merge.
Source
Thrown at Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/ExternalProgramMerger.java:581
if (s != null) {
return (s.getSource() == SourceType.USER_DEFINED);
}
return false;
}
/**
* Removes the indicated external library from the indicated program version
* if it is empty.
* @param program the program
* @param libName the external library name
* @throws InvalidInputException if there is no such enterrnal library in the program
*/
private void removeExternalLibrary(Program program, String libName)
throws InvalidInputException {
ExternalManager extMgr = program.getExternalManager();
ExternalLocationIterator iter = extMgr.getExternalLocations(libName);
if (iter.hasNext()) {
throw new InvalidInputException(
"Didn't remove external library " + libName + " since it isn't empty.");
}
if (!extMgr.removeExternalLibrary(libName)) {
throw new InvalidInputException("Didn't remove external library " + libName);
}
}
/**
* Determines whether the latest external program name and my external program name are equals.
* @param latestName the latest external program name or null.
* @param myName my external program name or null.
* @return true if the names are equal.
*/
private boolean same(String latestName, String myName) {
return SystemUtilities.isEqual(latestName, myName);
}
/**View on GitHub (pinned to d5f144c24d)
Solutions
- Remove or relocate the external locations in the library before attempting to remove the library.
- Keep the library instead of removing it; the exception is informational - catch it and append the message to infoBuf (as the merger's callers already do).
- Resolve the merge conflict in the GUI so the library/locations are consistent before check-in.
- In scripting, call extMgr.getExternalLocations(libName) first and only remove when iter is empty.
Example fix
// before
removeExternalLibrary(program, libName);
// library has locations -> InvalidInputException
// after
ExternalManager extMgr = program.getExternalManager();
if (!extMgr.getExternalLocations(libName).hasNext()) {
extMgr.removeExternalLibrary(libName);
} else {
infoBuf.append("Library " + libName + " not removed: still has external locations\n");
} Defensive patterns
Strategy: validation
Validate before calling
ExternalManager extMgr = program.getExternalManager();
boolean empty = !extMgr.getExternalLocations(libName).hasNext();
if (!empty) {
// do not call removeExternalLibrary; relocate or keep the library
} Type guard
boolean isExternalLibraryEmpty(Program p, String libName) {
return !p.getExternalManager().getExternalLocations(libName).hasNext();
} Try / catch
try {
removeExternalLibrary(program, libName);
} catch (InvalidInputException e) {
if (e.getMessage().contains("isn't empty")) {
// keep the library; log and continue
infoBuf.append(e.getMessage() + "\n");
} else throw e;
} Prevention
- Check getExternalLocations(libName).hasNext() before removing a library.
- Remove or relocate external locations first.
- Resolve library/location merge conflicts in the GUI before check-in.
When it happens
Trigger: During a multi-user program merge (version-control check-in), the merger attempts to remove an external library (because latest or 'my' version dropped it) but the result program still has external locations pointing into that library. Triggered by autoMergeWhenOnlyLatestChanged / autoMergeWhenOnlyMyChanged when latestName or myName is null.
Common situations: One branch deleted a library while another branch (or the result) still references its locations. Merge of programs where external locations were added but the library was simultaneously renamed/removed. Re-entrant merge state.
Related errors
- Didn't remove external library {libName}
- An external address translator can only handle a single addr
- Processor context register not allowed
- Invalid number of elements specified: {}
- pos cannot be less than zero
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/036572e9bd256990.
Report an issue: GitHub.