{"record":{"id":"d7e6846d6119c19a","repo":"NationalSecurityAgency/ghidra","slug":"function-list-cannot-be-empty-d7e684","errorCode":null,"errorMessage":"Function list cannot be empty","messagePattern":"Function list cannot be empty","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/facade/SFQueryInfo.java","lineNumber":60,"sourceCode":"\n\tprivate QueryNearest queryNearest;\n\tprivate BSimFilter bsimFilter;\n\tprivate PreFilter preFilter;\n\n\t/**\n\t * Constructs a query request with default parameters.\n\t * @param functions required--a set of functions (at least one) for which similar functions\n\t *                  will searched.  All functions must be from the same program.\n\t * @throws IllegalArgumentException if {@code functions} is {@code null}/empty or functions\n\t * are from multiple programs.  \n\t */\n\tpublic SFQueryInfo(Set<FunctionSymbol> functions) {\n\t\tif (functions == null) {\n\t\t\tthrow new IllegalArgumentException(\"Function list cannot be null\");\n\t\t}\n\n\t\tif (functions.isEmpty()) {\n\t\t\tthrow new IllegalArgumentException(\"Function list cannot be empty\");\n\t\t}\n\n\t\tthis.functions = functions;\n\t\tfor (FunctionSymbol s : functions) {\n\t\t\tif (program == null) {\n\t\t\t\tprogram = s.getProgram();\n\t\t\t}\n\t\t\telse if (program != s.getProgram()) {\n\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"all function symbols are not from the same program\");\n\t\t\t}\n\t\t}\n\t\tqueryNearest = new QueryNearest();\n\t\tbsimFilter = new BSimFilter();\n\t\tpreFilter = new PreFilter();\n\t}\n\n\t/**","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/facade/SFQueryInfo.java#L42-L78","documentation":"Thrown by the SFQueryInfo constructor when the Set<FunctionSymbol> functions is non-null but empty (isEmpty()). A similar-function query needs at least one source function to generate signatures; an empty set is an invalid request. Second ordered check after the null check.","triggerScenarios":"new SFQueryInfo(Set.of()) or a selection set that matched zero functions.","commonSituations":"User invokes BSim search with nothing selected; a filter excluded all symbols; a batch loop hit an item with no symbols.","solutions":["Guard at the action entry: skip SFQueryInfo construction when the set is empty and notify the user.","Validate selection contains at least one function symbol before enabling the search action.","In loops, continue rather than construct when the resolved set is empty."],"exampleFix":"// before\nSet<FunctionSymbol> syms = getSelectedFunctionSymbols();\nSFQueryInfo info = new SFQueryInfo(syms);\n// after\nSet<FunctionSymbol> syms = getSelectedFunctionSymbols();\nif (syms == null || syms.isEmpty()) { return; }\nSFQueryInfo info = new SFQueryInfo(syms);","handlingStrategy":"validation","validationCode":"if (functions == null || functions.isEmpty()) {\n    setStatusMessage(\"Select one or more functions\");\n    return;\n}\nSFQueryInfo info = new SFQueryInfo(functions);","typeGuard":"static boolean nonEmptyFunctions(Set<FunctionSymbol> fns) {\n    return fns != null && !fns.isEmpty();\n}","tryCatchPattern":"try {\n    new SFQueryInfo(functions);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"empty\")) { /* inform user */ }\n}","preventionTips":["Require at least one function symbol before enabling search.","Skip empty-set iterations in batch loops.","Handle emptiness at the UI, not at construction."],"tags":["bsim","facade","validation","argument-error","query"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}