NationalSecurityAgency/ghidra · error · IOException

Couldn't create file " + projectFile.getAbsolutePath()

Error message

Couldn't create file " + projectFile.getAbsolutePath()

What it means

Thrown as IOException by RestoreTask.createProjectMarkerFile when projectFile.createNewFile() returns false, meaning the marker file already exists or could not be created at the target path. RestoreTask creates this marker as part of restoring a project archive, so a failure here blocks the restore.

Source

Thrown at Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/archive/RestoreTask.java:112

		}
		catch (CancelledException ce) {
			plugin.cleanupRestoredProject(projectLocator);
			Msg.info(this, "Restore Archive: " + locInfo + " was cancelled by user.");
		}
		catch (Throwable e) {
			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);

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Delete the existing marker file (or the whole restore target) before re-running restore.
  2. Ensure the target project directory exists and is writable.
  3. Free disk space and check for locks on the target file.
  4. Catch IOException and report the absolute path so the user can fix permissions/conflicts.

Example fix

// before
if (!projectFile.createNewFile()) {
    throw new IOException("Couldn't create file " + projectFile.getAbsolutePath());
}

// after — clear stale marker first, and check parent writability
File parent = projectFile.getParentFile();
if (parent != null && !parent.exists() && !parent.mkdirs()) {
    throw new IOException("Couldn't create directory " + parent.getAbsolutePath());
}
if (projectFile.exists() && !projectFile.delete()) {
    throw new IOException("Existing marker not removable: " + projectFile.getAbsolutePath());
}
if (!projectFile.createNewFile()) {
    throw new IOException("Couldn't create file " + projectFile.getAbsolutePath());
}
Defensive patterns

Strategy: validation

Validate before calling

File parent = projectFile.getParentFile();
if (parent != null && !parent.exists() && !parent.mkdirs()) {
    throw new IOException("Couldn't create directory " + parent.getAbsolutePath());
}
if (projectFile.exists() && !projectFile.delete()) {
    throw new IOException("Existing marker not removable: " + projectFile.getAbsolutePath());
}

Type guard

boolean canCreate = projectFile.getParentFile() != null && projectFile.getParentFile().canWrite() && (!projectFile.exists() || projectFile.delete());

Try / catch

try {
    createProjectMarkerFile();
} catch (IOException e) {
    Msg.showError(this, null, "Restore Failed", e.getMessage());
}

Prevention

When it happens

Trigger: createNewFile() returns false because projectFile already exists (a previous restore left it), the parent directory does not exist or is not writable, or a permissions/lock issue prevents creation.

Common situations: Restoring an archive into a project directory that already contains a marker file from a prior restore; restoring to a read-only or non-existent directory; disk full or path too long; another process holds the file open.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/167222569d896ec4. Report an issue: GitHub.