skylot/jadx · error · JadxRuntimeException
Failed to read res-map file
Error message
Failed to read res-map file
What it means
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.
Source
Thrown at jadx-core/src/main/java/jadx/core/utils/android/TextResMapFile.java:32
import jadx.core.utils.exceptions.JadxRuntimeException;
public class TextResMapFile {
private static final int SPLIT_POS = 8;
public static Map<Integer, String> read(InputStream is) {
try (BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
Map<Integer, String> resMap = new HashMap<>();
while (true) {
String line = br.readLine();
if (line == null) {
break;
}
parseLine(resMap, line);
}
return resMap;
} catch (Exception e) {
throw new JadxRuntimeException("Failed to read res-map file", e);
}
}
private static void parseLine(Map<Integer, String> resMap, String line) {
int id = Integer.parseInt(line.substring(0, SPLIT_POS), 16);
String name = line.substring(SPLIT_POS + 1);
resMap.put(id, name);
}
public static Map<Integer, String> read(Path resMapFile) {
try (InputStream in = Files.newInputStream(resMapFile)) {
return read(in);
} catch (Exception e) {
throw new JadxRuntimeException("Failed to read res-map file", e);
}
}
public static void write(Path resMapFile, Map<Integer, String> inputResMap) {View on GitHub (pinned to e738a26571)
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().
Example fix
// before
Map<Integer,String> map = TextResMapFile.read(Files.newInputStream(path));
// after — guard against malformed lines by pre-validating
try (BufferedReader br = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
String line;
while ((line = br.readLine()) != null) {
if (!line.matches("^[0-9a-fA-F]{8}=.*$")) continue; // skip malformed
}
}
Map<Integer,String> map = TextResMapFile.read(Files.newInputStream(path)); Defensive patterns
Strategy: validation
Validate before calling
// Validate each line matches the '080028f0=name' format before calling read()
public static boolean isValidResMapFormat(Path path) throws IOException {
try (BufferedReader br = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
String line;
while ((line = br.readLine()) != null) {
if (line.isEmpty()) continue;
if (line.length() < 9 || line.charAt(8) != '=') return false;
String hexPart = line.substring(0, 8);
for (char c : hexPart.toCharArray()) {
if (Character.digit(c, 16) == -1) return false;
}
}
}
return true;
} Try / catch
try {
Map<Integer, String> map = TextResMapFile.read(inputStream);
} catch (JadxRuntimeException e) {
Throwable cause = e.getCause();
if (cause instanceof NumberFormatException || cause instanceof StringIndexOutOfBoundsException) {
LOG.error("Malformed res-map line: {}", cause.getMessage());
} else if (cause instanceof IOException) {
LOG.error("I/O error reading res-map: {}", cause.getMessage());
}
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Failed to write res-map file
- Can't parse type: {}, unexpected: {}
- Can not parse xml content
- Expected: 0x%08x, got: 0x%08x
- Failed to list files in directory: ${dir}
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/c894451049af6699.
Report an issue: GitHub.