{"record":{"id":"b1634cf9a8dc078a","repo":"iBotPeaches/Apktool","slug":"missing-key-string-pool","errorCode":null,"errorMessage":"Missing key string pool","messagePattern":"Missing key string pool","errorType":"exception","errorClass":"AndrolibException","httpStatus":null,"severity":"error","filePath":"brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/BinaryResourceParser.java","lineNumber":327,"sourceCode":"        mIn.skipShort(); // typesCount\n        int entryCount = mIn.readInt();\n\n        skipUnreadHeader(parser);\n\n        if (mEntrySpecFlagsOffsets != null) {\n            mEntrySpecFlagsOffsets.add(Pair.of(mIn.position(), entryCount));\n        }\n        mIn.skipBytes(entryCount * 4); // flags\n\n        mPackage.addTypeSpec(id, mTypeStringPool.getString(id - 1));\n    }\n\n    private void parseType(ResChunkPullParser parser) throws AndrolibException, IOException {\n        if (mTypeStringPool == null) {\n            throw new AndrolibException(\"Missing type string pool.\");\n        }\n        if (mKeyStringPool == null) {\n            throw new AndrolibException(\"Missing key string pool\");\n        }\n\n        // ResTable_type\n        int id = mIn.readUnsignedByte() - mTypeIdOffset;\n        int flags = mIn.readUnsignedByte();\n        mIn.skipShort(); // reserved\n        int entryCount = mIn.readInt();\n        int entriesStart = mIn.readInt();\n        ResConfig config = parseConfig();\n\n        skipUnreadHeader(parser);\n\n        // #3311 - Some older apps have no TYPE_SPEC chunks, but still define TYPE chunks.\n        ResTypeSpec typeSpec;\n        try {\n            typeSpec = mPackage.getTypeSpec(id);\n        } catch (UndefinedResObjectException ignored) {\n            typeSpec = mPackage.addTypeSpec(id, mTypeStringPool.getString(id - 1));","sourceCodeStart":309,"sourceCodeEnd":345,"githubUrl":"https://github.com/iBotPeaches/Apktool/blob/79b63384d7d7e22917e6ea8b453272da7012515b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/BinaryResourceParser.java#L309-L345","documentation":"parseType also requires the package's key (resource name) string pool before decoding entries, since each entry's key index must be resolved to a name. A RES_TABLE_TYPE chunk found before the RES_TABLE_TYPE_KEY string pool chunk triggers this.","triggerScenarios":"Malformed or deliberately obfuscated arsc where the key string pool chunk is missing or ordered after the type chunks within a package.","commonSituations":"Same family as [25]/[26]: packer-mangled resources.arsc, buggy resource optimizers, or fuzzed/corrupt artifacts. Frequently co-occurs with 'Missing type string pool.' because both pools live in the same header region of the package.","solutions":["Validate the arsc with aapt2; failure there confirms the file, not apktool, is at fault.","Source an unobfuscated copy of the APK for decoding.","When building arsc yourself, emit both type and key string pools immediately after the package header, before any type data.","Attach the failing arsc to an apktool GitHub issue if it comes from a real-world app."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    apkDecoder.decode(apk, out);\n} catch (AndrolibException e) {\n    if (\"Missing key string pool\".equals(e.getMessage())) {\n        // key-name pool missing or out of order — malformed arsc\n    }\n}","preventionTips":["Emit type and key string pools immediately after the package header when authoring arsc.","Run aapt2 validation on any arsc you patch or generate."],"tags":["apktool","arsc","parsing","chunk-order","obfuscation"],"backgroundTag":null,"analyzedSha":"79b63384d7d7e22917e6ea8b453272da7012515b","analyzedAt":"2026-08-14T10:43:28.812Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}