iBotPeaches/Apktool · error · AndrolibException
Missing value string pool.
Error message
Missing value string pool.
What it means
When a resource value has type TYPE_STRING, BinaryResourceParser resolves its data field as an index into the table's global value string pool. If no RES_TABLE_VALUE_POOL / string pool of type values was parsed before the entries, that lookup is impossible and this error is thrown.
Source
Thrown at brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/BinaryResourceParser.java:685
int type = mIn.readUnsignedByte();
int data = mIn.readInt();
return parseItem(typeName, inBag, type, data);
}
private ResValue parseItem(String typeName, boolean inBag, int type, int data) throws AndrolibException {
// ID resource values are either encoded as a boolean (false) or a resource reference.
// A boolean (false) is no longer allowed in XML, replace with a placeholder value.
// A resource reference is handled normally, unless it's @null.
if (typeName.equals("id") && (data == 0 || (type != ResValue.TYPE_REFERENCE
&& type != ResValue.TYPE_DYNAMIC_REFERENCE))) {
return ResCustom.ID;
}
// Special handling for strings and file references.
if (type == ResValue.TYPE_STRING) {
if (mValueStringPool == null) {
throw new AndrolibException("Missing value string pool.");
}
CharSequence strValue = mValueStringPool.getText(data);
// If a string is not allowed here, assume it's a file reference.
// ResFileDecoder will replace it if it's an invalid file reference.
if (strValue instanceof String && strValue.length() > 0 && !inBag && !typeName.equals("string")) {
return new ResFileReference((String) strValue);
}
return new ResString(strValue);
}
return ResItem.parse(mPackage, type, data);
}
private void parseLibrary(ResChunkPullParser parser) throws IOException {
// ResTable_lib_headerView on GitHub (pinned to 79b63384d7)
Solutions
- Verify the table header's string pool chunk exists and precedes package data (hex-dump around offset 0x0C).
- Decode an unobfuscated build of the same app.
- If producing arsc programmatically, always emit the global value string pool even when it looks empty.
- Report the sample upstream — apktool sometimes adds tolerances for known packer quirks.
Defensive patterns
Strategy: try-catch
Try / catch
try {
parser.parse(in);
} catch (AndrolibException e) {
if ("Missing value string pool.".equals(e.getMessage())) {
// table-level value string pool stripped but still referenced
}
} Prevention
- Never strip the global value string pool when shrinking arsc files.
- Test resource-optimized builds by decoding them before release.
When it happens
Trigger: An arsc whose package entries reference string values while the table-level value string pool chunk is missing or was skipped — typically a stripped/obfuscated pool or a chunk-order violation at table scope (not package scope).
Common situations: Packers that remove 'unused' string pools while leaving references to them; resource optimizers with bugs that drop the value pool when it still has live references; malformed fuzzing corpora.
Related errors
- Missing type string pool.
- Missing key string pool
- Input file is empty.
- Unexpected chunk:
- Could not decode arsc file.
AI-assisted analysis of iBotPeaches/Apktool@79b63384d7 (2026-08-14).
Data as JSON: /api/errors/e148b650edaf2922.
Report an issue: GitHub.