iBotPeaches/Apktool · error · UndefinedResObjectException

entry spec: pkgId=0x%02x, typeId=0x%02x, entryId=0x%04x

Error message

entry spec: pkgId=0x%02x, typeId=0x%02x, entryId=0x%04x

What it means

UndefinedResObjectException thrown by ResPackage.getEntrySpec(typeId, entryId) when no ResEntrySpec is registered for the resource id (after alias resolution). Entry specs carry the entry's name and flags; their absence means the table has no entry metadata for that (typeId, entryId) — the id is dangling, or belongs to another package, or aliases point somewhere unregistered.

Source

Thrown at brut.apktool/apktool-lib/src/main/java/brut/androlib/res/table/ResPackage.java:175

    public boolean hasEntrySpec(int typeId, int entryId) {
        ResId resId = ResId.of(getId(), typeId, entryId);
        resId = mAliases.getOrDefault(resId, resId);

        return mEntrySpecs.containsKey(resId);
    }

    public ResEntrySpec getEntrySpec(int typeId, int entryId) throws UndefinedResObjectException {
        ResId resId = ResId.of(getId(), typeId, entryId);
        if (mAliases.containsKey(resId)) {
            resId = mAliases.get(resId);
            typeId = resId.typeId();
            entryId = resId.entryId();
        }

        ResEntrySpec entrySpec = mEntrySpecs.get(resId);
        if (entrySpec == null) {
            throw new UndefinedResObjectException(
                String.format("entry spec: pkgId=0x%02x, typeId=0x%02x, entryId=0x%04x", getId(), typeId, entryId));
        }
        return entrySpec;
    }

    public ResEntrySpec addEntrySpec(int typeId, int entryId, String name) throws AndrolibException {
        ResId resId = ResId.of(getId(), typeId, entryId);
        if (mAliases.containsKey(resId)) {
            resId = mAliases.get(resId);
            typeId = resId.typeId();
            entryId = resId.entryId();
        }

        ResEntrySpec entrySpec = mEntrySpecs.get(resId);
        if (entrySpec != null) {
            throw new AndrolibException(
                String.format("Repeated entry spec: pkgId=0x%02x, typeId=0x%02x, entryId=0x%04x",
                    getId(), typeId, entryId));

View on GitHub (pinned to 79b63384d7)

Solutions

  1. Guard with hasEntrySpec-style check or catch UndefinedResObjectException before proceeding.
  2. Confirm the package id byte of the resource id matches the ResPackage you are querying.
  3. For aliases, verify the chain ends at a real entry: resolveAlias then check the target exists.
  4. Decode base + split APKs together so all entry specs are present.

Example fix

// before
ResEntrySpec spec = pkg.getEntrySpec(typeId, entryId);

// after
try {
    ResEntrySpec spec = pkg.getEntrySpec(typeId, entryId);
} catch (UndefinedResObjectException e) {
    // resource id is dangling in this package; skip or report
}
Defensive patterns

Strategy: try-catch

Validate before calling

ResId id = ResId.of(pkg.getId(), typeId, entryId);
// cheap pre-check via public API before getEntrySpec
boolean exists;
try { pkg.getEntrySpec(typeId, entryId); exists = true; }
catch (UndefinedResObjectException e) { exists = false; }

Try / catch

try {
    ResEntrySpec spec = pkg.getEntrySpec(typeId, entryId);
} catch (UndefinedResObjectException ex) {
    // dangling resource id in this package; log id and skip
}

Prevention

When it happens

Trigger: Resolving a resource id that exists in code/manifest but not in this package's table; obfuscated arsc where entry specs were stripped or renamed; an alias (mAliases) mapping to a final id that itself has no entry spec; calling before addEntrySpec during programmatic builds.

Common situations: Decoding obfuscated apps with collapsed/renamed resource names; split APKs where an entry lives in a different split; tools generating resource ids without matching arsc entries.

Related errors


AI-assisted analysis of iBotPeaches/Apktool@79b63384d7 (2026-08-14). Data as JSON: /api/errors/144c6b30a1d565ff. Report an issue: GitHub.