skylot/jadx · error · RuntimeException
Failed to parse code annotations
Error message
Failed to parse code annotations
What it means
CodeMetadataAdapter.readAndBuild reads a cached .jadxmd file to reconstruct code annotations. If the file is corrupted, truncated, or written by an incompatible jadx version, deserialization fails and a RuntimeException is thrown. This only triggers when a pre-existing cache file exists.
Source
Thrown at jadx-gui/src/main/java/jadx/gui/cache/code/disk/CodeMetadataAdapter.java:65
writeLines(out, metadata.getLineMapping());
writeAnnotations(out, metadata.getAsMap());
} catch (Exception e) {
throw new RuntimeException("Failed to write metadata file", e);
}
}
public ICodeInfo readAndBuild(Path metadataFile, String code) {
if (!Files.exists(metadataFile)) {
return new SimpleCodeInfo(code);
}
try (InputStream fileInput = Files.newInputStream(metadataFile);
DataInputStream in = new DataInputStream(new BufferedInputStream(fileInput))) {
in.skipBytes(JADX_METADATA_HEADER.length);
Map<Integer, Integer> lines = readLines(in);
Map<Integer, ICodeAnnotation> annotations = readAnnotations(in);
return new AnnotatedCodeInfo(code, lines, annotations);
} catch (Exception e) {
throw new RuntimeException("Failed to parse code annotations", e);
}
}
private void writeLines(DataOutput out, Map<Integer, Integer> lines) throws IOException {
out.writeInt(lines.size());
for (Map.Entry<Integer, Integer> entry : lines.entrySet()) {
DataAdapterHelper.writeUVInt(out, entry.getKey());
DataAdapterHelper.writeUVInt(out, entry.getValue());
}
}
private Map<Integer, Integer> readLines(DataInput in) throws IOException {
int size = in.readInt();
if (size == 0) {
return Collections.emptyMap();
}
Map<Integer, Integer> lines = new HashMap<>(size);
for (int i = 0; i < size; i++) {View on GitHub (pinned to e738a26571)
Solutions
- Clear the jadx cache directory to force a fresh decompilation
- Upgrade jadx — cache format version checks may have been added
- Ensure the cache directory is not shared across jadx versions
- Disable disk caching if the problem recurs
Example fix
// Clear cache to resolve format corruption: // rm -rf ~/.cache/jadx (or the configured cache dir) // Or set a fresh cache location in jadx-gui settings.
Defensive patterns
Strategy: fallback
Validate before calling
// Clear cache before loading if version changed
Path metaFile = cacheDir.resolve(clsId + ".jadxmd");
if (isIncompatibleVersion(metaFile)) { Files.deleteIfExists(metaFile); } Try / catch
// This is internal; the catch in readAndBuild rethrows. User remedy: // delete the cache directory to force fresh decompilation.
Prevention
- Clear cache after upgrading jadx
- Do not share cache across jadx versions
- Keep cache on stable local storage
When it happens
Trigger: readAndBuild opens the metadata file, skips the header, reads line mappings and annotations via DataInputStream. Any exception (EOFException, malformed UVInt, negative array size, version mismatch) is caught and wrapped. Called when loading a previously cached class from disk.
Common situations: Cache written by an older or newer jadx version with a different format. Cache file truncated by a crash or disk-full during a previous write. Cache directory modified or partially deleted by external processes. OS or antivirus corrupting cache files.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to write metadata file
- Failed to enumerate cached classes
- Failed to write caches file
- Failed to reset code cache
- Failed to remove code cache for {}
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/9275d4390f2a19de.
Report an issue: GitHub.