Tencent/tinker · error · TinkerRuntimeException
zipEntry is null when get from oldApk
Error message
zipEntry is null when get from oldApk
What it means
A defensive guard inside ResDiffPatchInternal's resource reconstruction loop: while enumerating entries of the base APK via TinkerZipFile.entries(), an element came back null. TinkerZipFile's enumeration is not expected to yield null, so hitting this indicates the old APK's central directory is damaged or the zip implementation returned an abnormal entry. It aborts resource patching before any output is trusted.
Source
Thrown at tinker-android/tinker-android-lib/src/main/java/com/tencent/tinker/lib/patch/ResDiffPatchInternal.java:150
TinkerZipOutputStream out = null;
TinkerZipFile oldApk = null;
TinkerZipFile newApk = null;
int totalEntryCount = 0;
try {
if (resOutput.exists()) {
resOutput.delete();
}
out = new TinkerZipOutputStream(new BufferedOutputStream(new FileOutputStream(resOutput)));
if (ShareTinkerInternals.isNewerOrEqualThanVersion(33, true)) {
resOutput.setReadOnly();
}
oldApk = new TinkerZipFile(apkPath);
newApk = new TinkerZipFile(patchFile);
final Enumeration<? extends TinkerZipEntry> entries = oldApk.entries();
while (entries.hasMoreElements()) {
TinkerZipEntry zipEntry = entries.nextElement();
if (zipEntry == null) {
throw new TinkerRuntimeException("zipEntry is null when get from oldApk");
}
String name = zipEntry.getName();
if (name.contains("../")) {
continue;
}
if (ShareResPatchInfo.checkFileInPattern(resPatchInfo.patterns, name)) {
//won't contain in add set.
if (!resPatchInfo.deleteRes.contains(name)
&& !resPatchInfo.modRes.contains(name)
&& !resPatchInfo.largeModRes.contains(name)
&& !name.equals(ShareConstants.RES_MANIFEST)) {
TinkerZipUtil.extractTinkerEntry(oldApk, zipEntry, out);
totalEntryCount++;
}
}
}
//process manifestView on GitHub (pinned to 1b7ea02c23)
Solutions
- Validate the installed base APK integrity (e.g., re-verify its signature or CRC) before distributing resource patches.
- Rebuild/re-sign the base APK with standard zipalign + apksigner and confirm it opens cleanly with ZipFile before shipping patches.
- Reinstall the base APK on affected devices; local corruption cannot be fixed by a patch.
- If unfixable on some devices, disable resource patching (TINKER_DISABLE for res) so dex/so patches still apply.
Defensive patterns
Strategy: validation
Validate before calling
try {
ZipFile apk = new ZipFile(context.getApplicationInfo().sourceDir);
Enumeration<? extends ZipEntry> es = apk.entries();
while (es.hasMoreElements()) { es.nextElement(); } // walk to surface corruption early
apk.close();
} catch (IOException e) {
// base APK zip is unreadable: skip patching, prompt reinstall
} Try / catch
try {
TinkerInstaller.onReceiveUpgradePatch(context, patchPath);
} catch (TinkerRuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("zipEntry is null")) {
disableResPatching(); // recover with dex/so only next time
}
} Prevention
- Distribute base APKs through channels that preserve file integrity (checksummed CDN transfer).
- Zipalign and sign release APKs with apksigner; avoid zip post-processing that rewrites central directories.
- Treat this exception as base-APK corruption: reinstall the app rather than re-applying patches.
When it happens
Trigger: During patchResource with an old APK whose ZIP structure is corrupt (truncated central directory, overlapping entries, or a zip flavor TinkerZipFile iterates abnormally), entries.nextElement() returns null on some iteration.
Common situations: Base APK corrupted on disk or by a repack/signing step; APK served through a CDN or hot-fix channel that truncated it; v2-signing-only zips processed by an older zip reader; extremely large resource tables triggering partial-entry reads.
Related errors
- patch %s extract failed (%s).
- file name:${filename}, file size${fileSize}, entry name:${en
- Not a zip archive
- Local file header offset is after central directory
- Duplicate entry name: ${entryName}
AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14).
Data as JSON: /api/errors/69325d0d47125ce8.
Report an issue: GitHub.