Tencent/tinker · error · TinkerRuntimeException
can't recognize dex mode:{}
Error message
can't recognize dex mode:{} What it means
ShareDexDiffPatchInfo's constructor validates the dexMode field from the patch's dex meta entry: it must be exactly ShareConstants.DEXMODE_JAR ('jar') or DEXMODE_RAW ('raw'). Anything else throws TinkerRuntimeException('can't recognize dex mode:'). The value comes from the meta.txt inside the patch package, which is generated by the tinker gradle plugin — so an unrecognized mode means a malformed/foreign meta file or a producer-consumer version skew.
Source
Thrown at tinker-android/tinker-android-loader-no-op/src/main/java/com/tencent/tinker/loader/shareutil/ShareDexDiffPatchInfo.java:69
this.path = path;
this.destMd5InDvm = destMd5InDvm;
this.destMd5InArt = destMd5InArt;
this.dexDiffMd5 = dexDiffMd5;
this.oldDexCrC = oldDexCrc;
this.newOrPatchedDexCrC = newOrPatchedDexCrC;
this.dexMode = dexMode;
if (dexMode.equals(ShareConstants.DEXMODE_JAR)) {
this.isJarMode = true;
if (SharePatchFileUtil.isRawDexFile(name)) {
realName = name + ShareConstants.JAR_SUFFIX;
} else {
realName = name;
}
} else if (dexMode.equals(ShareConstants.DEXMODE_RAW)) {
this.isJarMode = false;
this.realName = name;
} else {
throw new TinkerRuntimeException("can't recognize dex mode:" + dexMode);
}
}
public static void parseDexDiffPatchInfo(String meta, ArrayList<ShareDexDiffPatchInfo> dexList) {
if (meta == null || meta.length() == 0) {
return;
}
String[] lines = meta.split("\n");
for (final String line : lines) {
if (line == null || line.length() <= 0) {
continue;
}
final String[] kv = line.split(",", 8);
if (kv == null || kv.length < 8) {
continue;
}
// keyView on GitHub (pinned to 1b7ea02c23)
Solutions
- Regenerate the patch with the same tinker gradle plugin version as the runtime/loader in the base APK.
- Reject and clean the bad patch: catch the exception during patch apply and call cleanPatch().
- Verify meta-file integrity by validating the whole patch md5 before onReceiveUpgradePatch so tampered packages never reach parsing.
- Do not hand-edit patch packages or meta files.
Example fix
// before: passing any mode string
new ShareDexDiffPatchInfo(name, md5, crc, mode); // may throw
// after: validate before constructing
if (!ShareConstants.DEXMODE_JAR.equals(mode) && !ShareConstants.DEXMODE_RAW.equals(mode)) {
throw new IOException("bad dex mode in meta: " + mode);
} Defensive patterns
Strategy: validation
Validate before calling
static boolean isValidDexMode(String mode) {
return ShareConstants.DEXMODE_JAR.equals(mode) || ShareConstants.DEXMODE_RAW.equals(mode);
} Try / catch
try {
ShareDexDiffPatchInfo.parseDexDiffPatchInfo(meta, dexList);
} catch (TinkerRuntimeException e) {
// bad meta in patch package -> reject patch, do not install
reportInvalidPatch(e);
} Prevention
- Generate patches only with the matching plugin version
- Never hand-edit meta.txt or patch archives
- Verify patch package md5 before apply
When it happens
Trigger: parseDexDiffPatchInfo() splits the dex meta line and constructs ShareDexDiffPatchInfo with a mode string that is neither 'jar' nor 'raw' — e.g. a hand-edited or truncated meta file, a meta produced by a newer/older plugin using a different mode token, or a patch package crafted by an incompatible tool.
Common situations: Building the patch with a much newer tinker gradle plugin than the loader in the base APK; tampered patch packages; splitting logic bugs where the meta columns shift (extra comma/path with newline producing a wrong field alignment).
Related errors
- patch %s extract failed (%s).
- patch dex file directory not found, warning why the path is
- patch dex file not found, but path is null!!!!
- Unexpected header: 0x${headerSize}
- Unexpected endian tag: 0x${endianTag}
AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14).
Data as JSON: /api/errors/d87d7fb8d39056b5.
Report an issue: GitHub.