{"record":{"id":"9ba7f2171817db85","repo":"NationalSecurityAgency/ghidra","slug":"lasterror-message","errorCode":null,"errorMessage":"{lastError.message}","messagePattern":"\\{lastError\\.message\\}","errorType":"exception","errorClass":"LSHException","httpStatus":null,"severity":"error","filePath":"Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/ingest/BulkSignatures.java","lineNumber":850,"sourceCode":"\t\tMsg.info(this, buf.toString());\n\t}\n\n\t/**\n\t * Performs the work of inserting a new function tag name into the database. This \n\t * will build the query object, establish the database connection, and perform the query.\n\t * \n\t * @param tagName the tag name to insert\n\t * @throws IOException if there's an error establishing the database connection\n\t * @throws LSHException if there's an error issuing the query\n\t */\n\tpublic void installTags(String tagName) throws IOException, LSHException {\n\t\tDatabaseInformation info = establishQueryServerConnection(false);\n\t\tInstallTagRequest req = new InstallTagRequest();\n\t\treq.tag_name = dequoteString(tagName);\n\t\tResponseInfo resp = req.execute(querydb);\n\t\tif (resp == null) {\n\t\t\tBSimError lastError = querydb.getLastError();\n\t\t\tthrow new LSHException(lastError.message);\n\t\t}\n\t\tinfo = resp.info;\n\n\t\tStringBuilder buf = new StringBuilder();\n\t\tbuf.append(\"BSim Database \");\n\t\tbuf.append(info.databasename);\n\t\tbuf.append(\" now contains:\\n\");\n\t\tformatFunctionTags(info.functionTags, buf);\n\n\t\t// TODO: Should this output differ for command-line vs workbench? debug only?\n\t\tMsg.info(this, buf.toString());\n\t}\n\n\tprotected static int readQueryPairs(XmlPullParser parser, int count, List<PairInput> pairs) {\n\t\tfor (int i = 0; i < count; ++i) {\n\t\t\tif (!parser.peek().isStart()) {\n\t\t\t\treturn i;\n\t\t\t}","sourceCodeStart":832,"sourceCodeEnd":868,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/ingest/BulkSignatures.java#L832-L868","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\npublic void installTags(String tagName) throws IOException, LSHException {\n    DatabaseInformation info = establishQueryServerConnection(false);\n    InstallTagRequest req = new InstallTagRequest();\n    req.tag_name = dequoteString(tagName);\n    ResponseInfo resp = req.execute(querydb);\n    if (resp == null) {\n        BSimError lastError = querydb.getLastError();\n        throw new LSHException(lastError.message);\n    }\n    ...\n}\n\n// after — pre-check and richer error\npublic void installTags(String tagName) throws IOException, LSHException {\n    DatabaseInformation info = establishQueryServerConnection(false);\n    if (info.functionTags != null && info.functionTags.contains(tagName)) {\n        Msg.warn(this, \"Tag '\" + tagName + \"' already exists; skipping install.\");\n        return;\n    }\n    InstallTagRequest req = new InstallTagRequest();\n    req.tag_name = dequoteString(tagName);\n    ResponseInfo resp = req.execute(querydb);\n    if (resp == null) {\n        BSimError lastError = querydb.getLastError();\n        throw new LSHException(\"InstallTag failed for '\" + tagName + \"': \" + lastError.message);\n    }\n    ...","handlingStrategy":"try-catch","validationCode":"// Pre-check if the tag already exists before installing\nDatabaseInformation info = querydb.getInfo();\nif (info.functionTags != null && info.functionTags.contains(tagName)) {\n    // Tag exists; skip or handle accordingly\n    return;\n}","typeGuard":"// No type guard applicable — tagName is a String parameter.\n// Validate non-blank before calling installTags:\nif (tagName == null || tagName.trim().isEmpty()) {\n    throw new IllegalArgumentException(\"tagName must not be blank\");\n}","tryCatchPattern":"try {\n    bulk.installTags(tagName);\n} catch (LSHException e) {\n    if (e.getMessage().contains(\"already exists\")) {\n        // benign — tag was already present\n    } else {\n        throw e;\n    }\n}","preventionTips":["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."],"tags":["bsim","database","tag-install","lsh-exception"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}