Tencent/tinker · error · DexException
Unexpected endian tag: 0x${endianTag}
Error message
Unexpected endian tag: 0x${endianTag} What it means
Thrown by TableOfContents.readHeader when the endian_tag (offset 40) is not DexFormat.ENDIAN_TAG (0x12345678). The dex format is little-endian-only in practice; the tag exists to catch byte-order confusion, and a wrong value usually means every int in the file is swapped relative to expectation.
Source
Thrown at third-party/aosp-dexutils/src/main/java/com/tencent/tinker/android/dex/TableOfContents.java:182
private void readHeader(Dex.Section headerIn) throws UnsupportedEncodingException {
byte[] magic = headerIn.readByteArray(8);
api = DexFormat.magicToApi(magic);
if (api == -1) {
throw new DexException("Unexpected magic: " + Arrays.toString(magic));
}
checksum = headerIn.readInt();
signature = headerIn.readByteArray(20);
fileSize = headerIn.readInt();
int headerSize = headerIn.readInt();
if (headerSize != SizeOf.HEADER_ITEM) {
throw new DexException("Unexpected header: 0x" + Integer.toHexString(headerSize));
}
int endianTag = headerIn.readInt();
if (endianTag != DexFormat.ENDIAN_TAG) {
throw new DexException("Unexpected endian tag: 0x" + Integer.toHexString(endianTag));
}
linkSize = headerIn.readInt();
linkOff = headerIn.readInt();
mapList.off = headerIn.readInt();
if (mapList.off == 0) {
throw new DexException("Cannot merge dex files that do not contain a map");
}
stringIds.size = headerIn.readInt();
stringIds.off = headerIn.readInt();
typeIds.size = headerIn.readInt();
typeIds.off = headerIn.readInt();
protoIds.size = headerIn.readInt();
protoIds.off = headerIn.readInt();
fieldIds.size = headerIn.readInt();
fieldIds.off = headerIn.readInt();
methodIds.size = headerIn.readInt();
methodIds.off = headerIn.readInt();
classDefs.size = headerIn.readInt();View on GitHub (pinned to 1b7ea02c23)
Solutions
- Checksum-validate; if invalid, replace the file — do not attempt to byte-swap dexes back.
- If you author dexes programmatically, write ENDIAN_TAG (0x12345678) little-endian at offset 40; compare against a d8-produced reference dex.
- Add an early magic+tag sanity filter to batch inputs.
Defensive patterns
Strategy: try-catch
Validate before calling
static boolean littleEndianTagOk(ByteBuffer b) { return b.getInt(40) == 0x12345678; } Try / catch
catch (DexException e) with 'Unexpected endian tag' -> classify corrupt; re-download/rebuild the artifact
Prevention
- Verify SHA-1 signature field (offset 12..31) before deep parsing to get a precise corruption diagnosis.
When it happens
Trigger: Reading a dex that was byte-swapped by a big-endian intermediary, a header written by a buggy custom generator, or (most commonly) a corrupt/garbage file that happened to pass the magic and header-size checks.
Common situations: Corruption cases dominate; occasionally custom build tooling that assembles headers field-by-field gets the tag wrong, or truncated files where reads land on unrelated bytes.
Related errors
- Unexpected header: 0x${headerSize}
- Unexpected magic: ${magic}
- Cannot merge dex files that do not contain a map
- Map is unsorted at ${section}
- can't recognize dex mode:{}
AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14).
Data as JSON: /api/errors/d3841a412a0ba195.
Report an issue: GitHub.