iBotPeaches/Apktool · error · UndefinedResObjectException
type: pkgId=0x%02x, typeId=0x%02x, config=%s
Error message
type: pkgId=0x%02x, typeId=0x%02x, config=%s
What it means
UndefinedResObjectException thrown by ResPackage.getType(typeId, config) when no ResType exists for the (typeId, config) pair. ResType objects represent a type in one specific configuration (e.g. drawable for en-us); the error means that type/config combination was never created, most commonly because the type has no entry under the requested (often default) configuration.
Source
Thrown at brut.apktool/apktool-lib/src/main/java/brut/androlib/res/table/ResPackage.java:126
public boolean hasType(int typeId) {
return hasType(typeId, ResConfig.DEFAULT);
}
public boolean hasType(int typeId, ResConfig config) {
Pair<Integer, ResConfig> typeKey = Pair.of(typeId, config);
return mTypes.containsKey(typeKey);
}
public ResType getType(int typeId) throws UndefinedResObjectException {
return getType(typeId, ResConfig.DEFAULT);
}
public ResType getType(int typeId, ResConfig config) throws UndefinedResObjectException {
Pair<Integer, ResConfig> typeKey = Pair.of(typeId, config);
ResType type = mTypes.get(typeKey);
if (type == null) {
throw new UndefinedResObjectException(
String.format("type: pkgId=0x%02x, typeId=0x%02x, config=%s", getId(), typeId, config));
}
return type;
}
public ResType addType(int typeId) throws UndefinedResObjectException {
return addType(typeId, ResConfig.DEFAULT);
}
public ResType addType(int typeId, ResConfig config) throws UndefinedResObjectException {
Pair<Integer, ResConfig> typeKey = Pair.of(typeId, config);
ResType type = mTypes.get(typeKey);
if (type != null) {
// We can safely skip adding existing types.
return type;
}
ResTypeSpec typeSpec = getTypeSpec(typeId);View on GitHub (pinned to 79b63384d7)
Solutions
- Use hasType(typeId, config) before getType(typeId, config).
- If you need any config, iterate the available configs for the type instead of assuming ResConfig.DEFAULT exists.
- When constructing tables, ensure addType(typeId, config) happens before any get for that pair.
Example fix
// before ResType type = pkg.getType(typeId); // implies ResConfig.DEFAULT // after ResConfig config = pkg.hasType(typeId, ResConfig.DEFAULT) ? ResConfig.DEFAULT : firstAvailableConfig(pkg, typeId); ResType type = pkg.getType(typeId, config);
Defensive patterns
Strategy: type-guard
Validate before calling
ResConfig config = pkg.hasType(typeId, ResConfig.DEFAULT)
? ResConfig.DEFAULT
: pickExistingConfig(pkg, typeId); Type guard
boolean hasTypeForConfig(ResPackage pkg, int typeId, ResConfig config) {
return pkg.hasType(typeId, config);
} Try / catch
try {
ResType type = pkg.getType(typeId, config);
} catch (UndefinedResObjectException ex) {
// no values for this type under requested config; try other configs or skip
} Prevention
- Never assume the default config exists for every type
- Enumerate available configs when handling localized/density resources
- Load all splits of an app bundle for full config coverage
When it happens
Trigger: Calling getType(typeId) which defaults to ResConfig.DEFAULT when the type only has non-default configs; looking up a config that exists for another type but not this one; programmatic construction calling get before addType.
Common situations: Resource tables where a string/drawable exists only for specific locales or densities; code assuming every type has a default-config entry; handling localized apps and app bundles with per-density splits.
Related errors
- entry: pkgId=0x%02x, typeId=0x%02x, entryId=0x%04x, config=%
- 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/b43cd5b75ce1465a.
Report an issue: GitHub.