beemdevelopment/Aegis · error · IOException
Unable to find pack.json in the root of the ZIP file
Error message
Unable to find pack.json in the root of the ZIP file
What it means
IconPackManager.importPack opens the uploaded ZIP and looks up the entry named "pack.json" at the archive root. When zipFile.getFileHeader returns null, the archive either has no such entry or only stores it in a subdirectory, so an IOException is raised and surfaced as IconPackException. This is the first sanity check that the file is actually an Aegis icon pack.
Solutions
- Repackage the ZIP so pack.json sits at the root (zip from inside the pack folder, not the parent)
- Verify the archive contents (e.g. unzip -l) and confirm pack.json is present and not renamed
- Re-download the icon pack from its official source
- Ensure the file being imported is an Aegis icon pack, not another archive type
Example fix
// before (shell) zip -r pack.zip aegis-icons/ # pack.json ends up at aegis-icons/pack.json // after (shell) cd aegis-icons && zip -r ../pack.zip . # pack.json at archive root
Defensive patterns
Strategy: validation
Validate before calling
java.util.zip.ZipFile zf = new java.util.zip.ZipFile(inFile);
boolean ok = zf.getEntry("pack.json") != null;
zf.close();
if (!ok) throw new IconPackException("pack.json missing at ZIP root"); Try / catch
try {
iconPackManager.importPack(file);
} catch (IconPackException e) {
if (e.getCause() instanceof IOException && e.getMessage().contains("pack.json")) {
UiHelper.showDialog(context, R.string.invalid_icon_pack);
}
} Prevention
- Zip the pack contents from inside the folder so pack.json stays at the root
- Verify with unzip -l before distributing
- Never rename pack.json
- Document the expected archive layout for pack authors
When it happens
Trigger: Calling importPack with a ZIP that lacks a root-level pack.json entry: a ZIP wrapping the pack in an extra folder (pack.json under mypack/pack.json), a random ZIP file, or an archive whose definition file was renamed.
Common situations: Users re-zipping an extracted icon pack so an extra top-level directory is introduced; downloading the wrong archive; tools that nest files when compressing a folder instead of its contents.
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 relative to 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/76bcf2f794bcb045.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/main/java/com/beemdevelopment/aegis/icons/IconPackManager.java:70
public void removeIconPack(IconPack pack) throws IconPackException {
try {
File dir = getIconPackDir(pack);
deleteDir(dir);
} catch (IOException e) {
throw new IconPackException(e);
}
_iconPacks.remove(pack);
}
public IconPack importPack(File inFile) throws IconPackException {
try {
// read and parse the icon pack definition file of the icon pack
ZipFile zipFile = new ZipFile(inFile);
FileHeader packHeader = zipFile.getFileHeader(_packDefFilename);
if (packHeader == null) {
throw new IOException("Unable to find pack.json in the root of the ZIP file");
}
IconPack pack;
byte[] defBytes;
try (ZipInputStream inStream = zipFile.getInputStream(packHeader)) {
defBytes = IOUtils.readAll(inStream);
pack = IconPack.fromBytes(defBytes);
}
// create a new directory to store the icon pack, based on the UUID and version
File packDir = getIconPackDir(pack);
if (!packDir.getCanonicalPath().startsWith(_iconsBaseDir.getCanonicalPath() + File.separator)) {
throw new IOException("Attempted to write outside of the parent directory");
}
if (packDir.exists()) {
throw new IconPackExistsException(pack);
}
IconPack existingPack = getIconPackByUUID(pack.getUUID());
if (existingPack != null) {View on GitHub (pinned to d6f4e5925a)