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;
            }

            // key

View on GitHub (pinned to 1b7ea02c23)

Solutions

  1. Regenerate the patch with the same tinker gradle plugin version as the runtime/loader in the base APK.
  2. Reject and clean the bad patch: catch the exception during patch apply and call cleanPatch().
  3. Verify meta-file integrity by validating the whole patch md5 before onReceiveUpgradePatch so tampered packages never reach parsing.
  4. 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

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


AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14). Data as JSON: /api/errors/d87d7fb8d39056b5. Report an issue: GitHub.