Tencent/tinker · critical · IllegalStateException
bad dex patch file version:
Error message
bad dex patch file version:
What it means
IllegalStateException from DexPatchFile.init: the magic matched but the patch format version short is neither VERSION_02 nor VERSION_03. The parsing code only understands these two formats, so patches written by a different (newer or older) generator are rejected.
Source
Thrown at tinker-commons/src/main/java/com/tencent/tinker/commons/dexpatcher/struct/DexPatchFile.java:86
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();
if (this.version > DexPatchFile.VERSION_02) {
this.patchedCallSiteIdSectionOffset = this.buffer.readInt();
this.patchedMethodHandlesSectionOffset = this.buffer.readInt();
}
this.patchedClassDefSectionOffset = this.buffer.readInt();View on GitHub (pinned to 1b7ea02c23)
Solutions
- Align Tinker versions: use the same release for the gradle plugin (tinker-patch-gradle-plugin) and the app's tinker-android dependency
- Upgrade both sides together after checking the supported format matrix
- Regenerate the patch with the matching toolchain
Defensive patterns
Strategy: validation
Validate before calling
short v = patchFileVersion; // read header short before full parse
if (v != DexPatchFile.VERSION_02 && v != DexPatchFile.VERSION_03) {
throw new IOException("unsupported patch format " + v + "; align Tinker versions");
} Try / catch
try {
new DexPatchFile(stream);
} catch (IllegalStateException e) {
if (String.valueOf(e.getMessage()).startsWith("bad dex patch file version")) {
// version skew: regenerate patch with matching plugin or upgrade loader
} else { throw e; }
} Prevention
- Lock tinker gradle plugin and tinker-android dependencies to the same release line
- Upgrade both ends together and run an end-to-end patch test before rollout
When it happens
Trigger: Applying a dex patch produced by a Tinker gradle plugin whose DexPatchGenerator writes a different version field than the DexPatchFile reader in the runtime loader accepts.
Common situations: Version skew: patch built with newer Tinker (new format) but app embeds an older tinker-android loader, or vice versa; third-party tools emitting their own patch format versions.
Related errors
- createDelegate failed
- can't recognize dex mode:{}
- patch file is null.
- old dex version mismatch! expetced:
- Unexpected type:
AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14).
Data as JSON: /api/errors/44cb6637d2abd226.
Report an issue: GitHub.