{"record":{"id":"ba8666897043c71b","repo":"NationalSecurityAgency/ghidra","slug":"all-function-symbols-are-not-from-the-same-program","errorCode":null,"errorMessage":"all function symbols are not from the same program","messagePattern":"all function symbols are not from the same program","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/facade/SFOverviewInfo.java","lineNumber":53,"sourceCode":"\t * Constructs an overview request with default parameters.\n\t * @param functions required--a set of functions (at least one) for which an overview will be \n\t * \t\t\t\t\tcomputed.  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 SFOverviewInfo(Set<FunctionSymbol> functions) {\n\t\tif (functions == null)\n\t\t\tthrow new IllegalArgumentException(\"Function list cannot be null\");\n\t\tif (functions.isEmpty())\n\t\t\tthrow new IllegalArgumentException(\"Function list cannot be empty\");\n\t\t\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\tqueryNearestVector = new QueryNearestVector();\n\t\tpreFilter = new PreFilter();\n\t}\n\t\n\t/**\n\t * @return the program from which all queried functions are from\n\t */\n\tpublic Program getProgram() {\n\t\treturn program;\n\t}\n\n\tpublic double getSimilarityThreshold() {\n\t\treturn queryNearestVector.thresh;\n\t}\n\t","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/facade/SFOverviewInfo.java#L35-L71","documentation":"Thrown by the SFOverviewInfo constructor when iterating the function set reveals symbols sourced from more than one Program. The overview query must target one program (one signature context, one address space); the constructor captures the first symbol's program and rejects any symbol whose getProgram() differs. It is the third ordered check.","triggerScenarios":"Passing a Set<FunctionSymbol> assembled from two open programs, or from a program plus a linked external/library program whose symbols leaked into the set.","commonSituations":"A multi-program selection in the listing; cross-program symbol sets built by a script that iterates several Program objects; stale set reused across program switches.","solutions":["Filter the set to a single Program before construction (e.g. partition by getProgram() and issue one overview per program).","At the UI layer, scope selection gathering to the active program only.","If you genuinely need cross-program similarity, run separate SFOverviewInfo/SFQueryInfo instances per program."],"exampleFix":"// before\nSet<FunctionSymbol> all = collectFromMultiplePrograms();\nSFOverviewInfo info = new SFOverviewInfo(all);\n// after\nMap<Program, Set<FunctionSymbol>> byProgram = all.stream()\n    .collect(Collectors.groupingBy(FunctionSymbol::getProgram, Collectors.toSet()));\nfor (Set<FunctionSymbol> per : byProgram.values()) {\n    SFOverviewInfo info = new SFOverviewInfo(per);\n}","handlingStrategy":"validation","validationCode":"// partition by program first\nMap<Program, Set<FunctionSymbol>> byProgram = functions.stream()\n    .collect(Collectors.groupingBy(FunctionSymbol::getProgram, Collectors.toSet()));\nfor (Set<FunctionSymbol> per : byProgram.values()) {\n    SFOverviewInfo info = new SFOverviewInfo(per);\n}","typeGuard":"static boolean singleProgram(Set<FunctionSymbol> fns) {\n    long programs = fns.stream().map(FunctionSymbol::getProgram).distinct().count();\n    return programs <= 1;\n}","tryCatchPattern":"try {\n    new SFOverviewInfo(functions);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"same program\")) { /* split and retry per program */ }\n}","preventionTips":["Scope selection gathering to the active program.","Partition cross-program sets before constructing any query info.","Drop external/library symbols whose Program differs from the target."],"tags":["bsim","facade","validation","multi-program","overview"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}