{"record":{"id":"5a0df667f7abe2c7","repo":"NationalSecurityAgency/ghidra","slug":"unable-to-find-program-programpath","errorCode":null,"errorMessage":"Unable to find program: \" + programPath","messagePattern":"Unable to find program: \" \\+ programPath","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Ghidra/Features/Base/src/main/java/ghidra/app/nav/LocationMemento.java","lineNumber":47,"sourceCode":"public class LocationMemento {\n\tprivate static final String PROGRAM_PATH = \"PROGRAM_PATH_\";\n\tprivate static final String PROGRAM_ID = \"PROGRAM_ID\";\n\tprivate static final String MEMENTO_CLASS = \"MEMENTO_CLASS\";\n\n\tprotected final ProgramLocation programLocation;\n\tprivate final Program program;\n\n\tpublic LocationMemento(Program program, ProgramLocation location) {\n\t\tthis.program = program;\n\t\tthis.programLocation = location;\n\t}\n\n\tpublic LocationMemento(SaveState saveState, Program[] programs) {\n\t\tString programPath = saveState.getString(PROGRAM_PATH, null);\n\t\tlong programID = saveState.getLong(PROGRAM_ID, -1);\n\t\tprogram = getProgram(programs, programPath, programID);\n\t\tif (program == null) {\n\t\t\tthrow new IllegalArgumentException(\"Unable to find program: \" + programPath);\n\t\t}\n\n\t\tprogramLocation = ProgramLocation.getLocation(program, saveState);\n\t\tif (programLocation == null) {\n\t\t\tthrow new IllegalArgumentException(\"Unable to create a program location!\");\n\t\t}\n\t}\n\n\tpublic boolean isValid() {\n\t\treturn program != null && programLocation != null;\n\t}\n\n\tprivate Program getProgram(Program[] programs, String pathName, long programID) {\n\t\tfor (Program potentialProgram : programs) {\n\t\t\tif (potentialProgram.getUniqueProgramID() == programID) {\n\t\t\t\treturn potentialProgram;\n\t\t\t}\n\t\t}","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Features/Base/src/main/java/ghidra/app/nav/LocationMemento.java#L29-L65","documentation":"Thrown as IllegalArgumentException from the LocationMemento(SaveState, Program[]) constructor when getProgram(programs, programPath, programID) cannot locate a program matching the saved path/ID in the supplied array. LocationMemento is a saved UI navigation state; restoring it requires the exact program it was captured against to be present and open.","triggerScenarios":"Restoring a LocationMemento (e.g. from a saved tool state or navigation history) where the program at programPath / programID is not among the provided programs array — program not open, renamed, moved, or from a different project.","commonSituations":"Reopening a Ghidra tool whose saved state references a program no longer in the project; restoring navigation across a project migration where program IDs changed; passing a subset of open programs that omits the referenced one.","solutions":["Ensure the referenced program is open in the tool and passed in the programs array before restoring the memento.","If the program was moved/renamed, update the saved state's PROGRAM_PATH or re-resolve by content.","Guard isValid() / null-check before constructing, and skip stale mementos gracefully.","Catch IllegalArgumentException and drop the navigation entry rather than crashing the restore."],"exampleFix":"// before\nLocationMemento m = new LocationMemento(saveState, programs); // throws if program absent\n\n// after — verify membership first\nString path = saveState.getString(LocationMemento.PROGRAM_PATH, null);\nboolean present = Arrays.stream(programs).anyMatch(p -> p.getDomainFile().getPathname().equals(path));\nif (!present) {\n    return null; // skip stale navigation entry\n}\nLocationMemento m = new LocationMemento(saveState, programs);","handlingStrategy":"validation","validationCode":"String path = saveState.getString(LocationMemento.PROGRAM_PATH, null);\nboolean present = Arrays.stream(programs)\n    .anyMatch(p -> p.getDomainFile().getPathname().equals(path));\nif (!present) return null; // skip stale memento","typeGuard":"boolean restorable = Arrays.stream(programs).anyMatch(p -> p.getDomainFile().getPathname().equals(path));","tryCatchPattern":"try {\n    m = new LocationMemento(saveState, programs);\n} catch (IllegalArgumentException e) {\n    // drop stale navigation entry\n}","preventionTips":["Ensure referenced programs are open and passed in the programs array before restore.","Update saved PROGRAM_PATH after project migrations.","Skip stale mementos rather than crashing the restore."],"tags":["ghidra","navigation","save-state","illegal-argument","ui"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}