iBotPeaches/Apktool · error · UndefinedResObjectException

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

Error message

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

What it means

UndefinedResObjectException thrown by ResPackage.getEntry(typeId, entryId, config) when no ResEntry exists for the (resource id, config) pair (after alias resolution). It means the entry spec may exist, but there is no concrete value for the requested configuration — e.g. the string has values only for other locales, or the drawable only for other densities.

Source

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

        return mEntries.containsKey(entryKey);
    }

    public ResEntry getEntry(int typeId, int entryId) throws UndefinedResObjectException {
        return getEntry(typeId, entryId, ResConfig.DEFAULT);
    }

    public ResEntry getEntry(int typeId, int entryId, ResConfig config) throws UndefinedResObjectException {
        ResId resId = ResId.of(getId(), typeId, entryId);
        if (mAliases.containsKey(resId)) {
            resId = mAliases.get(resId);
            typeId = resId.typeId();
            entryId = resId.entryId();
        }

        Pair<ResId, ResConfig> entryKey = Pair.of(resId, config);
        ResEntry entry = mEntries.get(entryKey);
        if (entry == null) {
            throw new UndefinedResObjectException(
                String.format("entry: pkgId=0x%02x, typeId=0x%02x, entryId=0x%04x, config=%s",
                    getId(), typeId, entryId, config));
        }
        return entry;
    }

    public ResEntry addEntry(int typeId, int entryId, ResValue value) throws AndrolibException {
        return addEntry(typeId, entryId, ResConfig.DEFAULT, value);
    }

    public ResEntry addEntry(int typeId, int entryId, ResConfig config, ResValue value) throws AndrolibException {
        ResId resId = ResId.of(getId(), typeId, entryId);
        if (mAliases.containsKey(resId)) {
            resId = mAliases.get(resId);
            typeId = resId.typeId();
            entryId = resId.entryId();
        }

View on GitHub (pinned to 79b63384d7)

Solutions

  1. Check existence for the exact config before getEntry, and fall back through other configs of the type if appropriate.
  2. For sparse/obfuscated tables, iterate the type's entries rather than random-accessing by (id, config).
  3. When decoding splits, load all splits so config coverage is complete.

Example fix

// before
ResEntry entry = pkg.getEntry(typeId, entryId, ResConfig.DEFAULT);

// after
ResType type = pkg.getType(typeId, ResConfig.DEFAULT);
ResEntry entry = type.hasEntry(entryId) ? pkg.getEntry(typeId, entryId, ResConfig.DEFAULT) : null;
Defensive patterns

Strategy: try-catch

Validate before calling

// Prefer existence check on the type before exact-config lookup
ResType type = pkg.getType(typeId, ResConfig.DEFAULT);
if (!type.hasEntry(entryId)) {
    // no value under this config; fall back to another config or skip
}

Try / catch

try {
    ResEntry entry = pkg.getEntry(typeId, entryId, config);
} catch (UndefinedResObjectException ex) {
    // entry has no value for this config; iterate other configs of the type
}

Prevention

When it happens

Trigger: Calling getEntry with ResConfig.DEFAULT when the entry only has config-specific values; requesting a locale/density combination that was never compiled; alias resolution landing on an id/config pair with no entry.

Common situations: Localizations where an entry is omitted from the default config; density-split bundles (drawable only in hdpi split); obfuscated tables with sparse entries (note apktool tracks hasSparseEntries for exactly this); programmatic lookups assuming every config has every entry.

Related errors


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