beemdevelopment/Aegis · error · IOException
Unable to find relative to the root of the ZIP file
Error message
Unable to find %s relative to the root of the ZIP file
What it means
After passing the path-safety check, importPack looks up each icon's relative filename as a ZIP entry at the archive root. If the entry is missing (zipFile.getFileHeader returns null), the pack definition references a file that isn't in the archive, so an IOException naming the missing relative path is thrown and wrapped as IconPackException.
Solutions
- Rebuild the ZIP so every icon file named in pack.json exists at the archive root
- Compare pack.json's icon list against the actual ZIP entries (unzip -l) and fix mismatches
- Re-download the icon pack from its official source
- If you authored the pack, add the missing icon files before redistributing
Example fix
// before (shell) zip pack.zip pack.json # forgot the icon files // after (shell) cd aegis-icons && zip ../pack.zip pack.json *.png
Defensive patterns
Strategy: validation
Validate before calling
java.util.zip.ZipFile zf = new java.util.zip.ZipFile(inFile);
for (IconPack.Icon icon : pack.getIcons()) {
if (zf.getEntry(icon.getRelativeFilename()) == null) {
throw new IconPackException("Missing ZIP entry: " + icon.getRelativeFilename());
}
}
zf.close(); Try / catch
try {
iconPackManager.importPack(file);
} catch (IconPackException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Unable to find")) {
UiHelper.showDialog(context, R.string.incomplete_icon_pack);
}
} Prevention
- Rebuild the archive so every icon in pack.json is present at the root
- Diff pack.json's icon list against actual ZIP entries before distribution
- Re-download packs instead of repairing them by hand
- Add a pack build script that fails if any listed icon is missing
When it happens
Trigger: Importing an icon pack where pack.json lists icons whose files were not added to the ZIP, were renamed, or live in a subdirectory while the definition expects them at the root.
Common situations: Pack author edits pack.json to add icons but forgets to add the image files before zipping; re-zipping introduces a nested folder so entries shift; icons deleted from the archive after the definition was written.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Unable to find pack.json in the root of the ZIP file
- Accounts.txt
- Unable to decode stream to bitmap
- Bad UUID format
- Attempted to write outside of the parent directory
AI-assisted analysis of beemdevelopment/Aegis@d6f4e5925a (2026-09-08).
Data as JSON: /api/errors/a0e5f24ad3b17b2f.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/main/java/com/beemdevelopment/aegis/icons/IconPackManager.java:103
throw new IconPackExistsException(pack);
}
IconPack existingPack = getIconPackByUUID(pack.getUUID());
if (existingPack != null) {
throw new IconPackExistsException(existingPack);
}
if (!packDir.exists() && !packDir.mkdirs()) {
throw new IOException(String.format("Unable to create directories: %s", packDir.toString()));
}
// extract each of the defined icons to the icon pack directory
for (IconPack.Icon icon : pack.getIcons()) {
File destFile = new File(packDir, icon.getRelativeFilename());
if (!destFile.getCanonicalPath().startsWith(packDir.getCanonicalPath() + File.separator)) {
throw new IOException("Attempted to write outside of the icon pack directory");
}
FileHeader iconHeader = zipFile.getFileHeader(icon.getRelativeFilename());
if (iconHeader == null) {
throw new IOException(String.format("Unable to find %s relative to the root of the ZIP file", icon.getRelativeFilename()));
}
// create new directories for this file if needed
File parent = destFile.getParentFile();
if (parent != null && !parent.exists() && !parent.mkdirs()) {
throw new IOException(String.format("Unable to create directories: %s", packDir.toString()));
}
try (ZipInputStream inStream = zipFile.getInputStream(iconHeader);
FileOutputStream outStream = new FileOutputStream(destFile)) {
IOUtils.copy(inStream, outStream);
}
// after successful copy of the icon, store the new filename
icon.setFile(destFile);
}
// write the icon pack definition file to the newly created directoryView on GitHub (pinned to d6f4e5925a)