shwenzhang/AndResGuard · error · java.io.IOException

can not found res dir in the apk or it is not a dir

Error message

can not found res dir in the apk or it is not a dir

What it means

AndResGuard unzips the APK and expects an Android resource directory named 'res' inside it. This IOException is thrown when the extracted 'res' directory cannot be found or the path exists but is not a directory, meaning the input APK has no standard resources folder to process.

Solutions

  1. Verify the input file is a valid APK containing a res/ directory: unzip -l app.apk | grep ' res/'
  2. If you have an .aab, build an APK (bundletool build-apks / assembleRelease) instead of feeding the AAB to AndResGuard
  3. Clean the output directory to remove stale/partial UNZIP_FILE_PATH output from a previous failed run
  4. Re-download or rebuild the APK if it is corrupt or truncated

Example fix

// before
java -jar andresguard.jar input.xapk
// after
bundletool build-apks --bundle=input.aab --output=app.apks
# extract the universal.apk and pass that to AndResGuard
Defensive patterns

Strategy: validation

Validate before calling

import java.util.zip.ZipFile;
static boolean apkHasResDir(File apk) {
  if (apk == null || !apk.isFile()) return false;
  try (ZipFile zf = new ZipFile(apk)) {
    return zf.getEntry("res/") != null && zf.getEntry("res/").isDirectory();
  } catch (IOException e) { return false; }
}
if (!apkHasResDir(inputApk)) throw new IllegalArgumentException("input is not an APK with res/: " + inputApk);

Type guard

static boolean isApkWithRes(File f) {
  return f != null && f.isFile() && f.length() > 0 && f.getName().endsWith(".apk");
}

Prevention

When it happens

Trigger: Running AndResGuard's decode() on an APK whose extracted output has no res/ directory (mRawResFile missing) or where res exists as a regular file rather than a directory.

Common situations: Input file is not actually an APK (e.g. an AAB, a XAPK/zip of APKs, a corrupted download); the APK was built without resources; or a previous partial run left a broken unzip output in the output directory.

Related errors


AI-assisted analysis of shwenzhang/AndResGuard@e4df245d82 (2026-09-12). Data as JSON: /api/errors/b89f95bfbdf1c158. Report an issue: GitHub.

Appendix: source

Thrown at AndResGuard-core/src/main/java/com/tencent/mm/androlib/ApkDecoder.java:106

    if (!config.mKeepRoot) {
      mOutResFile = new File(mOutDir.getAbsolutePath() + File.separator + TypedValue.RES_FILE_PATH);
    } else {
      mOutResFile = new File(mOutDir.getAbsolutePath() + File.separator + "res");
    }

    //这个需要混淆各个文件夹
    mRawResFile = new File(mOutDir.getAbsoluteFile().getAbsolutePath()
                           + File.separator
                           + TypedValue.UNZIP_FILE_PATH
                           + File.separator
                           + "res");
    mOutTempDir = new File(mOutDir.getAbsoluteFile().getAbsolutePath() + File.separator + TypedValue.UNZIP_FILE_PATH);

    //这里纪录原始res目录的文件
    Files.walkFileTree(mRawResFile.toPath(), new ResourceFilesVisitor());

    if (!mRawResFile.exists() || !mRawResFile.isDirectory()) {
      throw new IOException("can not found res dir in the apk or it is not a dir");
    }

    mOutTempARSCFile = new File(mOutDir.getAbsoluteFile().getAbsolutePath() + File.separator + "resources_temp.arsc");
    mOutARSCFile = new File(mOutDir.getAbsoluteFile().getAbsolutePath() + File.separator + "resources.arsc");

    String basename = apkFile.getName().substring(0, apkFile.getName().indexOf(".apk"));
    mResMappingFile = new File(mOutDir.getAbsoluteFile().getAbsolutePath()
                               + File.separator
                               + TypedValue.RES_MAPPING_FILE
                               + basename
                               + TypedValue.TXT_FILE);
    mMergeDuplicatedResMappingFile = new File(mOutDir.getAbsoluteFile().getAbsolutePath()
                             + File.separator
                             + TypedValue.MERGE_DUPLICATED_RES_MAPPING_FILE
                             + basename
                             + TypedValue.TXT_FILE);
  }

View on GitHub (pinned to e4df245d82)