{"record":{"id":"c75cfca330f8836d","repo":"iBotPeaches/Apktool","slug":"undefined-decoder-for-type-s","errorCode":null,"errorMessage":"Undefined decoder for type: %s","messagePattern":"Undefined decoder for type: (.+?)","errorType":"exception","errorClass":"AndrolibException","httpStatus":null,"severity":"warning","filePath":"brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResFileDecoder.java","lineNumber":111,"sourceCode":"                    // Assume the file is a raw PNG.\n                    // Some apps contain unprocessed dummy 3x3 9-patch PNGs.\n                    // Extract them as-is, let aapt2 process them properly later.\n                    Log.d(TAG, \"Could not find 9-patch chunk in file: \" + inFileName);\n                }\n            }\n\n            decode(Type.UNKNOWN, inDir, inFileName, outDir, outFileName);\n        } catch (AndrolibException ignored) {\n            Log.w(TAG, \"Could not decode file, replacing by NULL value: \" + inFileName);\n            entry.setValue(ResPrimitive.NULL);\n        }\n    }\n\n    private void decode(Type type, Directory inDir, String inFileName, Directory outDir, String outFileName)\n            throws AndrolibException {\n        ResStreamDecoder decoder = mDecoders.get(type);\n        if (decoder == null) {\n            throw new AndrolibException(\"Undefined decoder for type: \" + type);\n        }\n\n        boolean success = false;\n        try (\n            InputStream in = inDir.getFileInput(inFileName);\n            OutputStream out = outDir.getFileOutput(outFileName)\n        ) {\n            decoder.decode(in, out);\n            success = true;\n        } catch (DirectoryException | IOException ex) {\n            throw new AndrolibException(ex);\n        } finally {\n            if (!success) {\n                outDir.removeFile(outFileName);\n            }\n        }\n    }\n}","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/iBotPeaches/Apktool/blob/79b63384d7d7e22917e6ea8b453272da7012515b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResFileDecoder.java#L93-L129","documentation":"Thrown by ResFileDecoder's private decode(type, ...) when no ResStreamDecoder is registered in the decoder map for the requested Type (UNKNOWN, BINARY_XML, or PNG_9PATCH). It indicates the ResFileDecoder was constructed with an incomplete decoder map. The public decode(ResEntry, ...) entry point catches AndrolibException and replaces the value with ResPrimitive.NULL plus a warning, so direct impact is limited to callers of that public path or to a NULL resource appearing in output.","triggerScenarios":"Building ResFileDecoder with a map missing Type.UNKNOWN, Type.BINARY_XML (AXmlResourceParser), or Type.PNG_9PATCH; third-party code reusing ResFileDecoder with a custom partial map; refactoring that drops a decoder registration.","commonSituations":"Embedding apktool-lib and hand-assembling the decoder map instead of using the framework's default wiring; version upgrades where the Type enum gained values not present in an old map; test harnesses with stub decoders.","solutions":["Register a decoder for every ResFileDecoder.Type value, especially Type.UNKNOWN (typically ResRawStreamDecoder) since it is the fallback path.","Prefer using apktool's own wiring (ApkDecoder) rather than constructing ResFileDecoder manually.","After upgrade, re-check the Type enum and add mappings for any new values."],"exampleFix":"// before\nMap<ResFileDecoder.Type, ResStreamDecoder> decoders = new EnumMap<>(ResFileDecoder.Type.class);\ndecoders.put(ResFileDecoder.Type.BINARY_XML, xmlDecoder);\nnew ResFileDecoder(decoders); // UNKNOWN missing -> \"Undefined decoder for type: UNKNOWN\"\n\n// after\nMap<ResFileDecoder.Type, ResStreamDecoder> decoders = new EnumMap<>(ResFileDecoder.Type.class);\ndecoders.put(ResFileDecoder.Type.BINARY_XML, xmlDecoder);\ndecoders.put(ResFileDecoder.Type.PNG_9PATCH, ninePatchDecoder);\ndecoders.put(ResFileDecoder.Type.UNKNOWN, new ResRawStreamDecoder());\nnew ResFileDecoder(decoders);","handlingStrategy":"validation","validationCode":"// Register every Type before constructing ResFileDecoder\nMap<ResFileDecoder.Type, ResStreamDecoder> decoders = new EnumMap<>(ResFileDecoder.Type.class);\nfor (ResFileDecoder.Type t : ResFileDecoder.Type.values()) {\n    if (!decoders.containsKey(t)) throw new IllegalStateException(\"Missing decoder for \" + t);\n}","typeGuard":null,"tryCatchPattern":"try {\n    resFileDecoder.decode(entry, inDir, outDir, resFileMap);\n} catch (AndrolibException ex) {\n    // public path already downgrades to ResPrimitive.NULL; this only fires for misuse\n    Log.w(TAG, \"decode failed: \" + ex.getMessage(), ex);\n}","preventionTips":["Always map Type.UNKNOWN (raw copy fallback) in the decoder map","Prefer apktool's built-in ApkDecoder wiring over hand-built maps","After upgrading apktool-lib, re-check the Type enum for new values"],"tags":["android","apktool","decoder-registry","configuration","resources"],"backgroundTag":null,"analyzedSha":"79b63384d7d7e22917e6ea8b453272da7012515b","analyzedAt":"2026-08-14T10:43:28.812Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}