{"record":{"id":"c894451049af6699","repo":"skylot/jadx","slug":"failed-to-read-res-map-file","errorCode":null,"errorMessage":"Failed to read res-map file","messagePattern":"Failed to read res-map file","errorType":"exception","errorClass":"JadxRuntimeException","httpStatus":null,"severity":"error","filePath":"jadx-core/src/main/java/jadx/core/utils/android/TextResMapFile.java","lineNumber":32,"sourceCode":"\nimport jadx.core.utils.exceptions.JadxRuntimeException;\n\npublic class TextResMapFile {\n\tprivate static final int SPLIT_POS = 8;\n\n\tpublic static Map<Integer, String> read(InputStream is) {\n\t\ttry (BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {\n\t\t\tMap<Integer, String> resMap = new HashMap<>();\n\t\t\twhile (true) {\n\t\t\t\tString line = br.readLine();\n\t\t\t\tif (line == null) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tparseLine(resMap, line);\n\t\t\t}\n\t\t\treturn resMap;\n\t\t} catch (Exception e) {\n\t\t\tthrow new JadxRuntimeException(\"Failed to read res-map file\", e);\n\t\t}\n\t}\n\n\tprivate static void parseLine(Map<Integer, String> resMap, String line) {\n\t\tint id = Integer.parseInt(line.substring(0, SPLIT_POS), 16);\n\t\tString name = line.substring(SPLIT_POS + 1);\n\t\tresMap.put(id, name);\n\t}\n\n\tpublic static Map<Integer, String> read(Path resMapFile) {\n\t\ttry (InputStream in = Files.newInputStream(resMapFile)) {\n\t\t\treturn read(in);\n\t\t} catch (Exception e) {\n\t\t\tthrow new JadxRuntimeException(\"Failed to read res-map file\", e);\n\t\t}\n\t}\n\n\tpublic static void write(Path resMapFile, Map<Integer, String> inputResMap) {","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/skylot/jadx/blob/e738a26571d02919f01df40de93bc9a44dee4e18/jadx-core/src/main/java/jadx/core/utils/android/TextResMapFile.java#L14-L50","documentation":"Thrown when TextResMapFile.read(InputStream) fails to parse a text res-map file. The read loop delegates each line to parseLine, which expects exactly 8 hex characters at offset 0 (SPLIT_POS=8), followed by '=' and the resource name. Any malformed line (shorter than 8 chars, non-hex ID, missing '=') causes NumberFormatException or StringIndexOutOfBoundsException, which is caught and rewrapped as JadxRuntimeException. I/O failures during readLine() are also wrapped here.","triggerScenarios":"Calling TextResMapFile.read(InputStream) with a stream whose content does not conform to the '080028f0=resource_name' line format. Specifically: a line shorter than 8 characters (substring(0, SPLIT_POS) throws StringIndexOutOfBoundsException), a line whose first 8 chars are not valid hex (Integer.parseInt(..., 16) throws NumberFormatException), a line shorter than 9 chars (substring(SPLIT_POS + 1) throws), or a closed/null underlying stream (IOException from readLine).","commonSituations":"A user-edited or externally generated res-map file that uses a different delimiter (space, tab, colon) instead of '='. A file saved with CRLF where a stray '\\r' ends up in the hex portion. A truncated or corrupted res-map file from a failed extraction. A pipe/stream that was already closed before being passed in.","solutions":["Validate the res-map file format before passing it: every non-empty line must match the regex '^[0-9a-fA-F]{8}=..*$'.","If the file was hand-edited, re-export it via TextResMapFile.write so it uses the exact '%08x=%s' format.","Check the wrapped cause in the JadxRuntimeException (getCause()) to distinguish parse errors (NumberFormatException/StringIndexOutOfBoundsException) from I/O errors (IOException).","If reading from a stream, ensure the stream is open and not already consumed before calling read()."],"exampleFix":"// before\nMap<Integer,String> map = TextResMapFile.read(Files.newInputStream(path));\n\n// after — guard against malformed lines by pre-validating\ntry (BufferedReader br = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {\n    String line;\n    while ((line = br.readLine()) != null) {\n        if (!line.matches(\"^[0-9a-fA-F]{8}=.*$\")) continue; // skip malformed\n    }\n}\nMap<Integer,String> map = TextResMapFile.read(Files.newInputStream(path));","handlingStrategy":"validation","validationCode":"// Validate each line matches the '080028f0=name' format before calling read()\npublic static boolean isValidResMapFormat(Path path) throws IOException {\n    try (BufferedReader br = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {\n        String line;\n        while ((line = br.readLine()) != null) {\n            if (line.isEmpty()) continue;\n            if (line.length() < 9 || line.charAt(8) != '=') return false;\n            String hexPart = line.substring(0, 8);\n            for (char c : hexPart.toCharArray()) {\n                if (Character.digit(c, 16) == -1) return false;\n            }\n        }\n    }\n    return true;\n}","typeGuard":null,"tryCatchPattern":"try {\n    Map<Integer, String> map = TextResMapFile.read(inputStream);\n} catch (JadxRuntimeException e) {\n    Throwable cause = e.getCause();\n    if (cause instanceof NumberFormatException || cause instanceof StringIndexOutOfBoundsException) {\n        LOG.error(\"Malformed res-map line: {}\", cause.getMessage());\n    } else if (cause instanceof IOException) {\n        LOG.error(\"I/O error reading res-map: {}\", cause.getMessage());\n    }\n}","preventionTips":["Always generate res-map files using TextResMapFile.write so the format is guaranteed correct.","Never hand-edit res-map files; if you must, validate against the '^[0-9a-fA-F]{8}=..*$' regex.","Close streams only after read() returns to avoid IOException during readLine."],"tags":["parsing","res-map","file-io","jadx"],"backgroundTag":null,"analyzedSha":"e738a26571d02919f01df40de93bc9a44dee4e18","analyzedAt":"2026-08-14T00:10:24.238Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}