Tencent/tinker · error · DexException
Map is unsorted at ${section}
Error message
Map is unsorted at ${section} What it means
Thrown by TableOfContents.computeSizesFromOffsets when walking sections from the end of the file backwards: a section's offset is greater than the running end boundary (starting from fileSize). This means a section claims to start after a later section ends — i.e. the offset layout is inconsistent with the declared file size.
Source
Thrown at third-party/aosp-dexutils/src/main/java/com/tencent/tinker/android/dex/TableOfContents.java:251
Arrays.sort(sections);
// Skip header section, since its offset must be zero.
for (int i = 1; i < sections.length; ++i) {
if (sections[i].off == Section.UNDEF_OFFSET) {
sections[i].off = sections[i - 1].off;
}
}
}
public void computeSizesFromOffsets() {
int end = fileSize;
for (int i = sections.length - 1; i >= 0; i--) {
Section section = sections[i];
if (section.off == Section.UNDEF_OFFSET) {
continue;
}
if (section.off > end) {
throw new DexException("Map is unsorted at " + section);
}
section.byteCount = end - section.off;
end = section.off;
}
dataOff = header.byteCount
+ stringIds.byteCount
+ typeIds.byteCount
+ protoIds.byteCount
+ fieldIds.byteCount
+ methodIds.byteCount
+ classDefs.byteCount;
dataSize = fileSize - dataOff;
}
private Section getSection(short type) {
for (Section section : sections) {View on GitHub (pinned to 1b7ea02c23)
Solutions
- Compare the header fileSize field to the actual byte length of the file — a mismatch means truncation; re-fetch or rebuild the dex.
- If you author patchers, recompute fileSize, checksum, and signature together after any content change.
- Validate the SHA-1 signature field before parsing to catch truncation early with a clearer error.
Defensive patterns
Strategy: validation
Validate before calling
int declaredSize = headerBuf.getInt(32); // fileSize
if (declaredSize != actualFile.length()) throw new IOException("truncated dex: header says " + declaredSize + ", file is " + actualFile.length()); Prevention
- Compare declared fileSize to actual byte length before parsing — catches truncation in one cheap check.
- Transfer dex artifacts with size/hash verification (e.g. sha1 digest alongside the file).
When it happens
Trigger: A map/header where a section offset exceeds the actual file size (truncated file, fileSize field wrong, or offsets from a pre-truncation version of the dex).
Common situations: Truncated downloads or partial writes of dex files; patch pipelines that rewrite headers with a stale fileSize; fat binaries sliced incorrectly.
Related errors
- unknown section type: ${type}
- Unexpected header: 0x${headerSize}
- Unexpected endian tag: 0x${endianTag}
- No such map item: ${type}
- can't recognize dex mode:{}
AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14).
Data as JSON: /api/errors/a5aad63ba72d4bbf.
Report an issue: GitHub.