NationalSecurityAgency/ghidra · error · LSHException

Could not perform delete: {}

Error message

Could not perform delete: {}

What it means

Thrown in deleteExecutables when QueryDelete.execute(querydb) returns null, meaning the server could not perform the delete. BulkSignatures rethrows the last error message as an LSHException prefixed 'Could not perform delete:'. Unlike the Format/Nonfatal handling elsewhere, here any null response is fatal.

Source

Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/ingest/BulkSignatures.java:572

		deleteExecutables(spec);
	}

	/**
	 * Deletes a specified executable from the database.
	 * 
	 * @param spec the spec that indicates what executable to delete
	 * @throws IOException if there's an error establishing the database connection
	 * @throws LSHException if there's an error issuing the query
	 */
	protected void deleteExecutables(ExeSpecifier spec) throws IOException, LSHException {

		QueryDelete query = new QueryDelete();
		query.addSpecifier(spec);
		establishQueryServerConnection(true);
		ResponseDelete respdel = query.execute(querydb);
		if (respdel == null) {
			BSimError lastError = querydb.getLastError();
			throw new LSHException("Could not perform delete: " + lastError.message);
		}

		// TODO: Should this output differ for command-line vs workbench? debug only?
		for (DeleteResult delres : respdel.reslist) {
			Msg.info(this, "Successfully deleted " + delres.name + "(" +
				Integer.toString(delres.funccount) + " functions)" + delres.md5);
		}
		for (ExeSpecifier missedSpec : respdel.missedlist) {
			Msg.error(this, "Unable to uniquely identify: " + missedSpec.getExeNameWithMD5());
		}
	}

	/**
	 * Drops the current BSim database index which can allow for faster signature ingest after
	 * which a {@link #rebuildIndex()} may be performed.  Dropping the index may also be done to
	 * obtain more accurate results albeit at the cost of performance.
	 * 
	 * @throws IOException if there's an error establishing the database connection

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Read the LSHException message for the server's reason.
  2. Confirm the executable (md5/name) exists via getexeinfo before deleting.
  3. Verify the connecting user has delete privileges.
  4. Retry once if the message indicates a transient connection issue.

Example fix

// before
bsim.deleteExecutable(md5, null);  // md5 not in DB -> LSHException

// after
// verify the exe exists first, then delete
if (!bsim.getExecutableRecords(1, md5, null, null, null, false).isEmpty()) {
    bsim.deleteExecutable(md5, null);
}
Defensive patterns

Strategy: validation

Validate before calling

// confirm the executable exists before deleting
if (bsim.getExecutableRecords(1, md5, name, null, null, null, false).isEmpty()) {
    throw new NoSuchElementException("No executable for md5/name");
}
bsim.deleteExecutable(md5, name);

Try / catch

try {
    bsim.deleteExecutable(md5, name);
} catch (LSHException e) {
    // message: "Could not perform delete: <server>"; verify existence/privileges and retry if transient
}

Prevention

When it happens

Trigger: Deleting an executable whose specifier the server cannot resolve, a connection drop during the delete, insufficient privileges, or a backend error.

Common situations: md5/name do not match any stored executable (server still returns null on total miss in some backends); permissions; transient connection loss; DB in read-only mode.

Related errors


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