shwenzhang/AndResGuard · error · brut.androlib.AndrolibException

Could not decode arsc file

Error message

Could not decode arsc file

What it means

RawARSCDecoder.decode performs a raw first pass over resources.arsc to collect existing resource names. Any IOException while streaming the arsc (truncation, premature EOF, unreadable bytes) is wrapped into AndrolibException("Could not decode arsc file") with the original cause attached. It signals the arsc could not be parsed at the byte level.

Solutions

  1. Verify the APK: unzip -t app.apk and aapt dump badging; re-obtain a clean build if corrupt
  2. Rebuild the APK with standard Android build tooling and retry
  3. Check disk space and file permissions on the build machine
  4. Update AndResGuard; if the cause is a legit format change, the wrapped cause exception will say which read failed

Example fix

// before: feeding a corrupted apk
AndResGuard.process(brokenApk)
// after: validate first
// unzip -t app.apk && aapt dump badging app.apk
AndResGuard.process(verifiedApk)
Defensive patterns

Strategy: try-catch

Validate before calling

// verify apk/arsc integrity before decoding
Process p = new ProcessBuilder("aapt", "dump", "badging", apkPath).start();
if (p.waitFor() != 0) throw new IllegalArgumentException("APK is invalid: " + apkPath);

Try / catch

try {
  RawARSCDecoder.decode(arscStream);
} catch (AndrolibException e) {
  if ("Could not decode arsc file".equals(e.getMessage())) {
    logger.error("arsc unreadable (cause: " + e.getCause() + "); verify the apk is not corrupted");
    throw new BuildException("Corrupt resources.arsc — obtain a clean build", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: decoder.readTable() throws IOException — the arscStream ends prematurely (truncated file), the underlying zip entry cannot be read, or the byte stream is corrupted.

Common situations: Corrupted or partially downloaded APKs, APKs whose resources.arsc entry was damaged by another packing tool, filesystem/IO errors while reading the APK, or an encrypted/modified arsc entry.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

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

  private ResType mType;
  private int mTypeIdOffset = 0;
  private int mCurTypeID = -1;
  private ResPackage[] mPkgs;
  private int mResId;

  private RawARSCDecoder(InputStream arscStream) throws AndrolibException, IOException {
    arscStream = mCountIn = new CountingInputStream(arscStream);
    mIn = new ExtDataInput(new LEDataInputStream(arscStream));
    mExistTypeNames = new HashMap<>();
  }

  public static ResPackage[] decode(InputStream arscStream) throws AndrolibException {
    try {
      RawARSCDecoder decoder = new RawARSCDecoder(arscStream);
      System.out.printf("parse to get the exist names in the resouces.arsc first\n");
      return decoder.readTable();
    } catch (IOException ex) {
      throw new AndrolibException("Could not decode arsc file", ex);
    }
  }

  public static Set<String> getExistTypeSpecNameStrings(int type) {
    return mExistTypeNames.get(type);
  }

  private ResPackage[] readTable() throws IOException, AndrolibException {
    nextChunkCheckType(Header.TYPE_TABLE);
    int packageCount = mIn.readInt();
    StringBlock.read(mIn);
    ResPackage[] packages = new ResPackage[packageCount];
    nextChunk();
    for (int i = 0; i < packageCount; i++) {
      packages[i] = readTablePackage();
    }
    return packages;
  }

View on GitHub (pinned to e4df245d82)