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
- Guard with hasEntrySpec-style check or catch UndefinedResObjectException before proceeding.
- Confirm the package id byte of the resource id matches the ResPackage you are querying.
- For aliases, verify the chain ends at a real entry: resolveAlias then check the target exists.
- 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
- Treat UndefinedResObjectException as 'not present', not as fatal
- Verify package id byte matches before lookups
- Decode base + splits together so entry specs are complete
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
- type spec: pkgId=0x%02x, typeId=0x%02x
- type: pkgId=0x%02x, typeId=0x%02x, config=%s
- entry: pkgId=0x%02x, typeId=0x%02x, entryId=0x%04x, config=%
- overlayable: pkgId=0x%02x, name=%s
- Repeated alias: pkgId=0x%02x, aliasId=%s
AI-assisted analysis of iBotPeaches/Apktool@79b63384d7 (2026-08-14).
Data as JSON: /api/errors/144c6b30a1d565ff.
Report an issue: GitHub.