NationalSecurityAgency/ghidra · error · IOException
Not a zip file: " + fs.getFSRL()
Error message
Not a zip file: " + fs.getFSRL()
What it means
Thrown as IOException by RestoreTask.verifyArchive when the supplied filesystem's FSRL protocol is not "zip". Ghidra project archives (.gar) are zip-based, so verifyArchive rejects anything whose underlying filesystem is not a zip filesystem before checking for the marker file.
Source
Thrown at Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/archive/RestoreTask.java:118
plugin.cleanupRestoredProject(projectLocator);
String eMsg = (e.getMessage() != null) ? ":\n\n" + e.getMessage() : "";
Msg.showError(this, null, "Restore Archive Failed",
"An error occurred when restoring the project archive\n " + projectArchiveFile +
" to \n " + projectDir + eMsg,
e);
Msg.info(this, "Restore Archive: " + locInfo + " failed.");
}
}
private void createProjectMarkerFile() throws IOException {
if (!projectFile.createNewFile()) {
throw new IOException("Couldn't create file " + projectFile.getAbsolutePath());
}
}
private void verifyArchive(GFileSystem fs, TaskMonitor monitor) throws IOException {
if (!fs.getFSRL().getProtocol().equals("zip")) {
throw new IOException("Not a zip file: " + fs.getFSRL());
}
GFile magicFile = fs.lookup("/" + ArchivePlugin.JAR_VERSION_TAG);
if (magicFile == null) {
throw new IOException("Missing Ghidra Project Archive (.gar) marker file");
}
}
@Override
protected void processFile(GFile file, File destFSFile, TaskMonitor monitor)
throws IOException, CancelledException {
if (!shouldSkip(file)) {
super.processFile(file, destFSFile, monitor);
}
}
@Override
protected void processDirectory(GFile srcGFileDirectory, File destDirectory,
TaskMonitor monitor) throws IOException, CancelledException {View on GitHub (pinned to d5f144c24d)
Solutions
- Select a genuine Ghidra project archive (.gar) created by ArchivePlugin, which is a zip.
- Re-create the archive from a valid project if the file is corrupt or mis-typed.
- If the FS protocol is reported incorrectly, inspect fs.getFSRL() and re-open the file through the zip filesystem layer.
- Catch IOException and present a clear 'not a project archive' message to the user.
Example fix
// before
private void verifyArchive(GFileSystem fs, TaskMonitor monitor) throws IOException {
if (!fs.getFSRL().getProtocol().equals("zip")) {
throw new IOException("Not a zip file: " + fs.getFSRL());
}
...
}
// after — re-open via zip FS before rejecting, clearer error
private void verifyArchive(GFileSystem fs, TaskMonitor monitor) throws IOException {
if (!fs.getFSRL().getProtocol().equals("zip")) {
fs = FileSystemService.getInstance().openFileSystem(
fs.getFSRL().withProtocol("zip"), monitor);
}
if (!fs.getFSRL().getProtocol().equals("zip")) {
throw new IOException("Selected file is not a Ghidra project archive (.gar must be zip): " + fs.getFSRL());
}
...
} Defensive patterns
Strategy: validation
Validate before calling
if (!"zip".equals(fs.getFSRL().getProtocol())) {
// re-open through the zip filesystem layer or reject with a clear message
throw new IOException("Selected file is not a Ghidra project archive (must be zip): " + fs.getFSRL());
} Type guard
boolean isZip = "zip".equals(fs.getFSRL().getProtocol());
Try / catch
try {
verifyArchive(fs, monitor);
} catch (IOException e) {
Msg.showError(this, null, "Restore Failed", "Not a project archive: " + e.getMessage());
} Prevention
- Select a genuine .gar produced by ArchivePlugin.
- Re-create archives from a valid project when the file is mis-typed.
- Present a clear 'not a project archive' error to users.
When it happens
Trigger: Passing a GFileSystem whose getFSRL().getProtocol() is anything other than "zip" — e.g. a local-file ("file") filesystem, a gzip, a tar, or a custom FS — into RestoreTask.restore/verifyArchive.
Common situations: User selects a non-archive file (or a plain directory/zipped-non-project file) for project-archive restore; the file extension was renamed to .gar but the content is not a zip; a wrapper filesystem layer changed the reported protocol.
Related errors
- Missing Ghidra Project Archive (.gar) marker file
- Couldn't create file " + projectFile.getAbsolutePath()
- Bad filename in archive: \"" + filename + "\"
- Unsupported value: {}
- Invalid value for {}
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/09f9b82c1ea3f7ff.
Report an issue: GitHub.