{"record":{"id":"eeb8470965581ad5","repo":"NationalSecurityAgency/ghidra","slug":"could-not-determine-unique-executable","errorCode":null,"errorMessage":"Could not determine unique executable","messagePattern":"Could not determine unique executable","errorType":"exception","errorClass":"LSHException","httpStatus":null,"severity":"error","filePath":"Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/ingest/BulkSignatures.java","lineNumber":996,"sourceCode":"\t * @param resultFolder the folder where the results will be stored\n\t * @param query the query object containing the params of the query\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\tprotected void doDumpSigs(File resultFolder, QueryName query) throws IOException, LSHException {\n\t\tif (!resultFolder.isDirectory()) {\n\t\t\tthrow new IOException(resultFolder.getAbsolutePath() + \" is not a valid directory\");\n\t\t}\n\n\t\tDatabaseInformation info = establishQueryServerConnection(true);\n\t\tquery.fillinCallgraph = info.trackcallgraph;\n\t\tResponseName responseName = query.execute(querydb);\n\t\tif (responseName == null) {\n\t\t\tBSimError lastError = querydb.getLastError();\n\t\t\tthrow new LSHException(lastError.message);\n\t\t}\n\t\tif (!responseName.uniqueexecutable) {\n\t\t\tthrow new LSHException(\"Could not determine unique executable\");\n\t\t}\n\t\tExecutableRecord exe;\n\t\tif (!StringUtils.isAllBlank(query.spec.exemd5)) {\n\t\t\texe = responseName.manage.findExecutable(query.spec.exemd5);\n\t\t}\n\t\telse {\n\t\t\texe = responseName.manage.findExecutable(query.spec.exename, query.spec.arch,\n\t\t\t\tquery.spec.execompname);\n\t\t}\n\t\tString basename = \"sigs_\" + exe.getMd5();\n\t\tFile sigFile = new File(resultFolder, basename);\n\n\t\ttry (FileWriter writer = new FileWriter(sigFile)) {\n\t\t\tresponseName.manage.saveXml(writer);\n\t\t}\n\t}\n\n\tprotected File establishTemporaryDirectory(String xmldir) throws IOException {","sourceCodeStart":978,"sourceCodeEnd":1014,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/ingest/BulkSignatures.java#L978-L1014","documentation":"Thrown by doDumpSigs when the QueryName response has uniqueexecutable set to false. This means the query matched zero or more than one executable record, so the system cannot determine which one to dump signatures for. The method needs exactly one match to proceed.","triggerScenarios":"Querying by name when multiple executables share that name (common for generic names); querying by md5 that doesn't exist in the database (uniqueexecutable is false for empty results); querying by name without specifying architecture or compiler to disambiguate.","commonSituations":"Dumping by name 'libfoo.so' when multiple versions exist; the executable was never ingested into the database; name matches across different architectures; md5 hash has a typo.","solutions":["Query by md5 instead of name — md5 is unique by definition.","If querying by name, also provide arch and execompname to narrow the match.","Run a QueryName or queryinfo first to see how many executables match, then disambiguate.","Verify the executable was actually ingested into this BSim database."],"exampleFix":"// before\nif (!responseName.uniqueexecutable) {\n    throw new LSHException(\"Could not determine unique executable\");\n}\n\n// after — report what matched\nif (!responseName.uniqueexecutable) {\n    int count = responseName.manage.numExecutables();\n    throw new LSHException(\"Could not determine unique executable (matched \" +\n        count + \" records). Narrow by md5, or add arch/compiler qualifiers.\");\n}","handlingStrategy":"validation","validationCode":"// Pre-check uniqueness by running a count query\nQueryName precheck = new QueryName();\nprecheck.spec.exename = name;\nprecheck.spec.arch = arch;\nprecheck.spec.execompname = compiler;\nResponseName preResp = precheck.execute(querydb);\nif (preResp != null && !preResp.uniqueexecutable) {\n    int count = preResp.manage.numExecutables();\n    throw new IllegalStateException(\n        \"Name '\" + name + \"' matched \" + count + \" executables. \" +\n        \"Provide md5 or add arch/compiler qualifiers.\");\n}","typeGuard":"// Check the response before doDumpSigs proceeds to the uniqueexecutable check\npublic static boolean isUniqueMatch(ResponseName resp) {\n    return resp != null && resp.uniqueexecutable;\n}","tryCatchPattern":"try {\n    bulk.doDumpSigs(resultFolder, query);\n} catch (LSHException e) {\n    if (e.getMessage().contains(\"unique executable\")) {\n        // Query by md5 instead of name for uniqueness\n        query.spec.exemd5 = resolvedMd5;\n        query.spec.exename = null;\n        bulk.doDumpSigs(resultFolder, query);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Prefer md5 over name for executable identification — it is always unique.","When using name, always provide architecture and compiler qualifiers.","Run a pre-query to count matches before attempting a dump.","Log the number of matches when uniqueness fails."],"tags":["bsim","validation","dump-sigs","ambiguous-match"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}