shwenzhang/AndResGuard · error · java.io.IOException

the old mapping res file path should be like r/a, yours

Error message

the old mapping res file path should be like r/a, yours %s

What it means

During proguardFileName, when reusing an old resource-mapping file with keepMapping mode, every mapped value must be a path like "r/a" (res root directory + name, e.g. "res/mipmap-x" style prefix plus name). AndResGuard throws this IOException when a mapping value has no slash, so it cannot split it into the res root and the kept file name.

Solutions

  1. Open the old resource_mapping.txt and fix the offending line so values look like "res/dir/name" (contain at least one "/").
  2. Regenerate the mapping file from a previous successful AndResGuard run rather than hand-writing it.
  3. Ensure you use the mapping file version matching the AndResGuard version (format changed across versions).
  4. If you don't need to keep previous names, disable useKeepMapping so no old mapping is parsed.

Example fix

// before (mapping entry)
res/mipmap/ic_launcher -> ic_launcher
// after
res/mipmap/ic_launcher -> r/a
Defensive patterns

Strategy: validation

Validate before calling

for (String line : Files.readAllLines(mappingFile.toPath())) {
    int arrow = line.indexOf("->");
    String target = line.substring(arrow + 2).trim();
    if (!target.contains("/")) {
        throw new IllegalStateException("mapping value must be like r/a: " + target);
    }
}

Prevention

When it happens

Trigger: Running with config.useKeepMapping (keep resource names) where the resource_mapping.txt provided via config.mMappingFile contains a line whose new-name value lacks a "/" — e.g. a hand-edited mapping with just "icon" instead of "res/mipmap-x/icon" or "r/a".

Common situations: Manually edited or machine-generated mapping files from older/different tools with the wrong format; typos when preserving resource names via keepMapping; mapping copied from a different build whose format doesn't match.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

Thrown at AndResGuard-core/src/main/java/com/tencent/mm/androlib/res/decoder/ARSCDecoder.java:168

    for (File resFile : resFiles) {
      String raw = resFile.getName();
      if (raw.contains("-")) {
        raw = raw.substring(0, raw.indexOf("-"));
      }
      mShouldResguardTypeSet.add(raw);
    }

    if (!config.mKeepRoot) {
      // 需要保持之前的命名方式
      if (config.mUseKeepMapping) {
        HashMap<String, String> fileMapping = config.mOldFileMapping;
        List<String> keepFileNames = new ArrayList<>();
        // 这里面为了兼容以前,也需要用以前的文件名前缀,即res混淆成什么
        String resRoot = TypedValue.RES_FILE_PATH;
        for (String name : fileMapping.values()) {
          int dot = name.indexOf("/");
          if (dot == -1) {
            throw new IOException(String.format("the old mapping res file path should be like r/a, yours %s\n", name));
          }
          resRoot = name.substring(0, dot);
          keepFileNames.add(name.substring(dot + 1));
        }
        // 去掉所有之前保留的命名,为了简单操作,mapping里面有的都去掉
        mResguardBuilder.removeStrings(keepFileNames);

        for (File resFile : resFiles) {
          String raw = "res" + "/" + resFile.getName();
          if (fileMapping.containsKey(raw)) {
            mOldFileName.put(raw, fileMapping.get(raw));
          } else {
            mOldFileName.put(raw, resRoot + "/" + mResguardBuilder.getReplaceString());
          }
        }
      } else {
        for (int i = 0; i < resFiles.length; i++) {
          // 这里也要用linux的分隔符,如果普通的话,就是r

View on GitHub (pinned to e4df245d82)