Tencent/tinker · error · IllegalStateException
Binder transaction failure.
Error message
Binder transaction failure.
What it means
After resolving the transaction code, Tinker hand-crafts the binder parcel for performDexOptSecondary and calls IBinder.transact on the PMS binder proxy. transact returning false means the binder driver/framework refused the transaction, so the dexopt request was never delivered to PackageManagerService.
Source
Thrown at tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/TinkerDexOptimizer.java:399
sPerformDexOptSecondaryTransactionCode[0]);
final IBinder pmsBinder = getPMSBinderProxy(context);
Parcel data = null;
Parcel reply = null;
try {
data = Parcel.obtain();
reply = Parcel.obtain();
boolean result;
try {
data.writeInterfaceToken(pmsBinder.getInterfaceDescriptor());
data.writeString(context.getPackageName());
final String compileFilter = ShareTinkerInternals.isNewerOrEqualThanVersion(31 /* Android S */, true)
? "verify" : "speed-profile";
data.writeString(compileFilter);
data.writeInt(1); // force
boolean status = pmsBinder.transact(sPerformDexOptSecondaryTransactionCode[0], data, reply, 0);
if (!status) {
throw new IllegalStateException("Binder transaction failure.");
}
} catch (RemoteException e) {
throw new IllegalStateException(e);
}
try {
reply.readException();
} catch (Throwable thr) {
throw new IllegalStateException(thr);
}
result = (0 != reply.readInt());
if (!result) {
ShareTinkerLog.w(TAG, "[!] System API return false.");
}
} finally {
if (reply != null) {
reply.recycle();
}
if (data != null) {View on GitHub (pinned to 1b7ea02c23)
Solutions
- Update Tinker — newer versions re-check the transaction code and add fallbacks.
- Enable interpret mode to bypass the binder dexopt path entirely.
- Catch the IllegalStateException during patch load and degrade to interpretation instead of failing the patch.
Defensive patterns
Strategy: fallback
Try / catch
try {
pmsBinder.transact(code, data, reply, 0);
} catch (IllegalStateException e) {
// transact refused: fall back to interpret-only compilation
compileInterpretOnly(dexFile);
} Prevention
- Prefer interpret mode over binder-level dexopt on customized ROMs.
- Recompute the transaction code per process run; never cache across OS updates.
- Wrap patch load so a dexopt transport failure degrades instead of aborting.
When it happens
Trigger: pmsBinder.transact(...) returning false because the transaction code is stale for the running framework (e.g. code resolved on a different API shape), the binder died, or an OEM PMS rejects unknown transactions. Distinct from RemoteException, which is caught separately and wrapped.
Common situations: Mismatched transaction code after an OS upgrade (code cached from a prior boot class); OEM ROMs with a different IPackageManager parcel layout; the dexopt call racing with PMS restart.
Related errors
- Cannot query transaction code of performDexOptSecondary.
- No odex file was generated after calling performDexOptSecond
- target is null.
- fakeBinder does not return fakeInterface, binder: {}, itf: {
- No entries
AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14).
Data as JSON: /api/errors/53f5625397d3bc21.
Report an issue: GitHub.