{"record":{"id":"54d3d5986308b0df","repo":"NationalSecurityAgency/ghidra","slug":"database-getlasterror-message-54d3d5","errorCode":null,"errorMessage":"${database.getLastError().message}","messagePattern":"\\$\\{database\\.getLastError\\(\\)\\.message\\}","errorType":"exception","errorClass":"LSHException","httpStatus":null,"severity":"error","filePath":"Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/facade/SimilarFunctionQueryService.java","lineNumber":332,"sourceCode":"\t\t\tBSimQuery<?> stagedQuery = stagingManager.getQuery();\n\n\t\t\tQueryResponseRecord response = stagedQuery.execute(database);\n\t\t\tif (response != null) {\n\n\t\t\t\tif (globalResponse != response) {\n\t\t\t\t\tglobalResponse.mergeResults(response); // Merge the staged response with the global response\n\t\t\t\t}\n\n\t\t\t\tlistener.resultAdded(response);\n\n\t\t\t\thaveMore = stagingManager.nextStage();\n\t\t\t\tif (haveMore) {\n\t\t\t\t\tstagedQuery.clearResponse(); // Make space for next stage\n\t\t\t\t}\n\t\t\t\tmonitor.setProgress(stagingManager.getQueriesMade());\n\t\t\t}\n\t\t\telse {\n\t\t\t\tthrow new LSHException(database.getLastError().message);\n\t\t\t}\n\t\t}\n\n\t\treturn globalResponse;\n\t}\n\n\t/**\n\t * Return the {@link BSimServerInfo server info object} for this database\n\t * @return the server info object or null if not currently associated with \n\t * a {@link FunctionDatabase}.\n\t */\n\tpublic BSimServerInfo getServerInfo() {\n\t\tif (database == null) {\n\t\t\treturn null;\n\t\t}\n\t\treturn database.getServerInfo();\n\t}\n","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/facade/SimilarFunctionQueryService.java#L314-L350","documentation":"Thrown as an LSHException when a staged BSim query execution returns a null QueryResponseRecord, indicating the database failed to process the query. The actual cause is obtained from database.getLastError().message, which holds the last BSimError recorded by the underlying FunctionDatabase. This wraps the database-layer error so callers of SimilarFunctionQueryService see a consistent exception type.","triggerScenarios":"Occurs during executeStagedQuery() when stagedQuery.execute(database) returns null for any staged chunk of a similar-function query. Common triggers include a PostgreSQL/elastic/H2 BSim server going down mid-query, authentication session expiry during a long multi-stage query, a malformed query object that the database rejects, or the database encountering an internal error (e.g., connection dropped, SQL error) that sets lastError without throwing.","commonSituations":"Running a large BSim similarity search against a remote server over an unstable network. Querying a BSim database that was simultaneously dropped or restarted by another process. Using a database whose schema/layout version is incompatible with the client. Hitting a server-side timeout during a staged query with many functions.","solutions":["Check the message string from database.getLastError() (surfaced via LSHException.getMessage()) to find the underlying database error and address that root cause.","Verify the BSim server is reachable and healthy (use SimilarFunctionQueryService.getDatabaseStatus() to confirm Status.Ready before querying).","Reduce the number of stages or functions per query to shorten individual round-trips, reducing exposure to mid-query failures.","If the error indicates a layout/version mismatch, regenerate or migrate the BSim database to match the client's LAYOUT_VERSION.","Implement a retry with re-initialization (call initializeDatabase again) if the error is transient (network blip, server restart)."],"exampleFix":"// before\nQueryResponseRecord response = stagedQuery.execute(database);\nif (response == null) {\n    throw new LSHException(database.getLastError().message);\n}\n\n// after (caller-side: retry on transient failure)\ntry {\n    service.querySimilarFunctions(query, listener, monitor);\n} catch (LSHException e) {\n    if (isTransient(e.getMessage())) {\n        service.initializeDatabase(url); // reconnect\n        service.querySimilarFunctions(query, listener, monitor);\n    } else {\n        throw e;\n    }\n}","handlingStrategy":"try-catch","validationCode":"// Validate database is ready before querying\nif (service.getDatabaseStatus() != Status.Ready) {\n    throw new IllegalStateException(\n        \"BSim database not ready: \" + service.getDatabaseStatus());\n}","typeGuard":null,"tryCatchPattern":"try {\n    service.querySimilarFunctions(query, listener, monitor);\n} catch (LSHException e) {\n    FunctionDatabase.BSimError lastErr = service.getLastError();\n    String detail = (lastErr != null) ? lastErr.message : e.getMessage();\n    if (isTransientDatabaseError(detail)) {\n        service.initializeDatabase(originalUrl); // reconnect and retry\n        service.querySimilarFunctions(query, listener, monitor);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Always check getDatabaseStatus() == Status.Ready before issuing queries.","For long multi-stage queries, implement checkpointing so partial results survive a mid-query failure.","Keep the BSim server URL and connection parameters stable during a query session to avoid mid-flight reconnection issues.","Log service.getLastError() immediately after any query exception to capture the root database error."],"tags":["bsim","database","query-execution","lsh"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}