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
- Check existence for the exact config before getEntry, and fall back through other configs of the type if appropriate.
- For sparse/obfuscated tables, iterate the type's entries rather than random-accessing by (id, config).
- 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
- Check type-level entry existence before exact (id, config) lookups
- Handle sparse/obfuscated tables by iteration, not random access
- Load density/locale splits together with the base APK
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
- type: pkgId=0x%02x, typeId=0x%02x, config=%s
- type spec: pkgId=0x%02x, typeId=0x%02x
- entry spec: pkgId=0x%02x, typeId=0x%02x, entryId=0x%04x
- overlayable: pkgId=0x%02x, name=%s
- Stream advanced past chunk end.
AI-assisted analysis of iBotPeaches/Apktool@79b63384d7 (2026-08-14).
Data as JSON: /api/errors/a21fc6a2341fcfbd.
Report an issue: GitHub.