NationalSecurityAgency/ghidra · error · IOException

Bad xml directory

Error message

Bad xml directory

What it means

Thrown by BulkSignatures.gatherXml when File.listFiles() returns null. listFiles() returns null when the path is not a directory or is otherwise inaccessible, so the method cannot enumerate XML files. BulkSignatures uses this to collect signature ('sigs_*') and update ('update_*') files for ingest.

Source

Thrown at Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/ingest/BulkSignatures.java:157

	public void close() {
		closeConnection();
	}

	/**
	 * Closes the current database connection.
	 */
	private void closeConnection() {
		if (querydb != null) {
			querydb.close();
			querydb = null;
		}
	}

	private List<File> gatherXml(String prefix, File dir) throws IOException {
		List<File> res = new ArrayList<File>();
		File[] listFiles = dir.listFiles();
		if (listFiles == null) {
			throw new IOException("Bad xml directory");
		}
		for (File file : listFiles) {
			if (file.getName().startsWith(prefix)) {
				res.add(file);
			}
		}
		return res;
	}

	private void loadSignatureXml(File file, DescriptionManager manage)
			throws SAXException, IOException, LSHException {
		ErrorHandler handler = SpecXmlUtils.getXmlHandler();
		XmlPullParser parser = new NonThreadedXmlPullParserImpl(file, handler, false);
		manage.restoreXml(parser, querydb.getLSHVectorFactory());
	}

	protected void sendXmlToQueryServer(File dir, URL ghidraOverrideURL, String filter,
			TaskMonitor monitor)

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Ensure dir is an existing, readable directory (not a file).
  2. Create the directory before ingest if it does not yet exist.
  3. Fix filesystem read permissions on the directory.
  4. Pass the directory that contains the sigs_*/update_* files, not a single file.

Example fix

// before
bsim.sendSignaturesToServer(new File("out/sigs_0.xml"), null, monitor);  // not a dir

// after
bsim.sendSignaturesToServer(new File("out"), null, monitor);  // the directory
Defensive patterns

Strategy: validation

Validate before calling

File dir = new File(path);
if (!dir.exists() || !dir.isDirectory() || !dir.canRead()) {
    throw new IOException("Not a readable directory: " + path);
}
bsim.sendSignaturesToServer(dir, filter, monitor);

Type guard

private static boolean isReadableDir(File f) {
    return f != null && f.exists() && f.isDirectory() && f.canRead();
}

Prevention

When it happens

Trigger: Calling sendSignaturesToServer/sendUpdateToServer (which call gatherXml) with a dir argument that is a regular file, does not exist, or is unreadable due to permissions.

Common situations: Passing the XML file path instead of its containing directory; a generated-output directory was cleaned or never created; filesystem permission restrictions; path typo.

Related errors


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