NationalSecurityAgency/ghidra · error · LSHException
{lastError.message}
Error message
{lastError.message} What it means
Thrown by BulkSignatures.installTags when an InstallTagRequest fails at the database level. The method calls establishQueryServerConnection to connect, then executes the tag-install query; if the query returns null, it reads the underlying BSimError from querydb.getLastError() and wraps its message in an LSHException. The actual root cause is inside that BSimError — the tag may already exist, the connection may have dropped, or the server rejected the operation.
Source
Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/ingest/BulkSignatures.java:850
Msg.info(this, buf.toString());
}
/**
* Performs the work of inserting a new function tag name into the database. This
* will build the query object, establish the database connection, and perform the query.
*
* @param tagName the tag name to insert
* @throws IOException if there's an error establishing the database connection
* @throws LSHException if there's an error issuing the query
*/
public void installTags(String tagName) throws IOException, LSHException {
DatabaseInformation info = establishQueryServerConnection(false);
InstallTagRequest req = new InstallTagRequest();
req.tag_name = dequoteString(tagName);
ResponseInfo resp = req.execute(querydb);
if (resp == null) {
BSimError lastError = querydb.getLastError();
throw new LSHException(lastError.message);
}
info = resp.info;
StringBuilder buf = new StringBuilder();
buf.append("BSim Database ");
buf.append(info.databasename);
buf.append(" now contains:\n");
formatFunctionTags(info.functionTags, buf);
// TODO: Should this output differ for command-line vs workbench? debug only?
Msg.info(this, buf.toString());
}
protected static int readQueryPairs(XmlPullParser parser, int count, List<PairInput> pairs) {
for (int i = 0; i < count; ++i) {
if (!parser.peek().isStart()) {
return i;
}View on GitHub (pinned to d5f144c24d)
Solutions
- Check whether the tag already exists by running a 'queryinfo' command against the same database before attempting install.
- Verify the BSim server URL and credentials in the connection configuration — re-run with a known-good connect string.
- Inspect the BSimError returned by querydb.getLastError() in a debugger or log to read the exact server-side message; it is not surfaced in the thrown exception beyond lastError.message.
- If the tag genuinely should not exist, drop it first or use the appropriate overwrite/admin path.
Example fix
// before
public void installTags(String tagName) throws IOException, LSHException {
DatabaseInformation info = establishQueryServerConnection(false);
InstallTagRequest req = new InstallTagRequest();
req.tag_name = dequoteString(tagName);
ResponseInfo resp = req.execute(querydb);
if (resp == null) {
BSimError lastError = querydb.getLastError();
throw new LSHException(lastError.message);
}
...
}
// after — pre-check and richer error
public void installTags(String tagName) throws IOException, LSHException {
DatabaseInformation info = establishQueryServerConnection(false);
if (info.functionTags != null && info.functionTags.contains(tagName)) {
Msg.warn(this, "Tag '" + tagName + "' already exists; skipping install.");
return;
}
InstallTagRequest req = new InstallTagRequest();
req.tag_name = dequoteString(tagName);
ResponseInfo resp = req.execute(querydb);
if (resp == null) {
BSimError lastError = querydb.getLastError();
throw new LSHException("InstallTag failed for '" + tagName + "': " + lastError.message);
}
... Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check if the tag already exists before installing
DatabaseInformation info = querydb.getInfo();
if (info.functionTags != null && info.functionTags.contains(tagName)) {
// Tag exists; skip or handle accordingly
return;
} Type guard
// No type guard applicable — tagName is a String parameter.
// Validate non-blank before calling installTags:
if (tagName == null || tagName.trim().isEmpty()) {
throw new IllegalArgumentException("tagName must not be blank");
} Try / catch
try {
bulk.installTags(tagName);
} catch (LSHException e) {
if (e.getMessage().contains("already exists")) {
// benign — tag was already present
} else {
throw e;
}
} Prevention
- Run queryinfo before installtag to check existing tags.
- Use consistent tag naming to avoid accidental duplicates.
- Log the BSimError message for diagnosis when installTags fails.
When it happens
Trigger: Calling installTags(tagName) against a live BSim server where the InstallTagRequest.execute(querydb) call returns null. This happens when the server reports an error (e.g., tag already exists, authentication failure, or a database constraint violation). The dequoteString preprocessing does not guard against duplicates.
Common situations: Running 'bsim installtag' on a tag name that already exists in the target database; pointing at a PostgreSQL or Elasticsearch BSim backend whose connection credentials are wrong or expired; network interruption between the client and the BSim server during the query.
Related errors
- Self-score not recorded for
- Optional table does not exist when it should:
- Unable to initialize new thresholds:
- Database does not exist
- Password entry was cancelled
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/9ba7f2171817db85.
Report an issue: GitHub.