iBotPeaches/Apktool · warning · AndrolibException

Undefined decoder for type: %s

Error message

Undefined decoder for type: %s

What it means

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.

Source

Thrown at brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/ResFileDecoder.java:111

                    // Assume the file is a raw PNG.
                    // Some apps contain unprocessed dummy 3x3 9-patch PNGs.
                    // Extract them as-is, let aapt2 process them properly later.
                    Log.d(TAG, "Could not find 9-patch chunk in file: " + inFileName);
                }
            }

            decode(Type.UNKNOWN, inDir, inFileName, outDir, outFileName);
        } catch (AndrolibException ignored) {
            Log.w(TAG, "Could not decode file, replacing by NULL value: " + inFileName);
            entry.setValue(ResPrimitive.NULL);
        }
    }

    private void decode(Type type, Directory inDir, String inFileName, Directory outDir, String outFileName)
            throws AndrolibException {
        ResStreamDecoder decoder = mDecoders.get(type);
        if (decoder == null) {
            throw new AndrolibException("Undefined decoder for type: " + type);
        }

        boolean success = false;
        try (
            InputStream in = inDir.getFileInput(inFileName);
            OutputStream out = outDir.getFileOutput(outFileName)
        ) {
            decoder.decode(in, out);
            success = true;
        } catch (DirectoryException | IOException ex) {
            throw new AndrolibException(ex);
        } finally {
            if (!success) {
                outDir.removeFile(outFileName);
            }
        }
    }
}

View on GitHub (pinned to 79b63384d7)

Solutions

  1. Register a decoder for every ResFileDecoder.Type value, especially Type.UNKNOWN (typically ResRawStreamDecoder) since it is the fallback path.
  2. Prefer using apktool's own wiring (ApkDecoder) rather than constructing ResFileDecoder manually.
  3. After upgrade, re-check the Type enum and add mappings for any new values.

Example fix

// before
Map<ResFileDecoder.Type, ResStreamDecoder> decoders = new EnumMap<>(ResFileDecoder.Type.class);
decoders.put(ResFileDecoder.Type.BINARY_XML, xmlDecoder);
new ResFileDecoder(decoders); // UNKNOWN missing -> "Undefined decoder for type: UNKNOWN"

// after
Map<ResFileDecoder.Type, ResStreamDecoder> decoders = new EnumMap<>(ResFileDecoder.Type.class);
decoders.put(ResFileDecoder.Type.BINARY_XML, xmlDecoder);
decoders.put(ResFileDecoder.Type.PNG_9PATCH, ninePatchDecoder);
decoders.put(ResFileDecoder.Type.UNKNOWN, new ResRawStreamDecoder());
new ResFileDecoder(decoders);
Defensive patterns

Strategy: validation

Validate before calling

// Register every Type before constructing ResFileDecoder
Map<ResFileDecoder.Type, ResStreamDecoder> decoders = new EnumMap<>(ResFileDecoder.Type.class);
for (ResFileDecoder.Type t : ResFileDecoder.Type.values()) {
    if (!decoders.containsKey(t)) throw new IllegalStateException("Missing decoder for " + t);
}

Try / catch

try {
    resFileDecoder.decode(entry, inDir, outDir, resFileMap);
} catch (AndrolibException ex) {
    // public path already downgrades to ResPrimitive.NULL; this only fires for misuse
    Log.w(TAG, "decode failed: " + ex.getMessage(), ex);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of iBotPeaches/Apktool@79b63384d7 (2026-08-14). Data as JSON: /api/errors/c75cfca330f8836d. Report an issue: GitHub.