Tencent/tinker · critical · IllegalStateException
bad dex patch file magic:
Error message
bad dex patch file magic:
What it means
IllegalStateException from DexPatchFile.init: the first bytes of the patch file do not equal the expected 'dexpatch' magic. The stream/file being parsed is not a Tinker dex patch file at all.
Source
Thrown at tinker-commons/src/main/java/com/tencent/tinker/commons/dexpatcher/struct/DexPatchFile.java:81
private int patchedAnnotationSectionOffset;
private int patchedEncodedArraySectionOffset;
private int patchedAnnotationsDirectorySectionOffset;
private byte[] oldDexSignature;
public DexPatchFile(File file) throws IOException {
this.buffer = new DexDataBuffer(ByteBuffer.wrap(FileUtils.readFile(file)));
init();
}
public DexPatchFile(InputStream is) throws IOException {
this.buffer = new DexDataBuffer(ByteBuffer.wrap(FileUtils.readStream(is)));
init();
}
private void init() {
byte[] magic = this.buffer.readByteArray(MAGIC.length);
if (CompareUtils.uArrCompare(magic, MAGIC) != 0) {
throw new IllegalStateException("bad dex patch file magic: " + Arrays.toString(magic));
}
this.version = this.buffer.readShort();
if (this.version != VERSION_02 && this.version != VERSION_03) {
throw new IllegalStateException("bad dex patch file version: " + this.version);
}
if (this.version > VERSION_02) {
this.oldDexAPI = this.buffer.readInt();
this.patchedDexAPI = this.buffer.readInt();
}
this.patchedDexSize = this.buffer.readInt();
this.firstChunkOffset = this.buffer.readInt();
this.patchedStringIdSectionOffset = this.buffer.readInt();
this.patchedTypeIdSectionOffset = this.buffer.readInt();
this.patchedProtoIdSectionOffset = this.buffer.readInt();
this.patchedFieldIdSectionOffset = this.buffer.readInt();
this.patchedMethodIdSectionOffset = this.buffer.readInt();View on GitHub (pinned to 1b7ea02c23)
Solutions
- Check the downloaded payload's content type and size before parsing; the printed magic bytes reveal what was actually received
- Extract the correctly-named patch entry (e.g., classes.dex patch entries) from the package
- Fix the patch download URL/delivery pipeline
Example fix
// before
new DexPatchFile(new FileInputStream(downloadedFile));
// after
byte[] head = new byte[8];
try (InputStream in = new FileInputStream(downloadedFile)) { in.read(head); }
if (!new String(head, "US-ASCII").startsWith("dexpatch")) throw new IOException("not a dex patch payload");
new DexPatchFile(new FileInputStream(downloadedFile)); Defensive patterns
Strategy: validation
Validate before calling
byte[] magic = new byte[8];
try (InputStream is = new BufferedInputStream(new FileInputStream(file))) {
if (is.read(magic) != magic.length || !"dexpatch".equals(new String(magic, 0, 8, "US-ASCII").trim())) {
throw new IOException("payload is not a dex patch file");
}
}
DexPatchFile pf = new DexPatchFile(new FileInputStream(file)); Try / catch
try {
new DexPatchFile(stream);
} catch (IllegalStateException e) {
if (String.valueOf(e.getMessage()).startsWith("bad dex patch file magic")) {
// log received bytes, fix download URL / extraction, do not parse further
} else { throw e; }
} Prevention
- Check Content-Type and length of downloaded patch responses before persisting them
- Extract patch entries by their exact names from the patch archive
When it happens
Trigger: Constructing DexPatchFile(File/InputStream) over content that is not a dex patch — e.g., a full dex, a zip entry of the wrong name, an HTML error page from a download endpoint, or a file read from offset 0 of the wrong resource.
Common situations: Patch server returning an error page instead of the patch; extracting the wrong entry from the patch zip; passing the old/new dex where the .dex patch was expected.
Related errors
- patch file is null.
- bad patch operation sequence. addCounter: %d, addCount: %d,
- Unexpected header: 0x${headerSize}
- Unexpected endian tag: 0x${endianTag}
- Map is unsorted at ${section}
AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14).
Data as JSON: /api/errors/3366edae3375f8b0.
Report an issue: GitHub.