Tencent/tinker · error · IllegalStateException
target is null.
Error message
target is null.
What it means
ServiceBinderInterceptor.decorate() wraps the IBinder fetched from ServiceManager.getService(serviceName) in a proxy. It throws IllegalStateException('target is null.') when that lookup returned null — the named system service is not currently registered, so there is nothing to intercept.
Source
Thrown at tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/hotplug/interceptor/ServiceBinderInterceptor.java:69
public ServiceBinderInterceptor(Context context, String serviceName, BinderInvocationHandler binderInvocationHandler) {
while (context != null && context instanceof ContextWrapper) {
context = ((ContextWrapper) context).getBaseContext();
}
mBaseContext = context;
mServiceName = serviceName;
mBinderInvocationHandler = binderInvocationHandler;
}
@Override
protected IBinder fetchTarget() throws Throwable {
return (IBinder) sGetServiceMethod.invoke(null, mServiceName);
}
@Override
protected IBinder decorate(IBinder target) throws Throwable {
if (target == null) {
throw new IllegalStateException("target is null.");
}
if (ITinkerHotplugProxy.class.isAssignableFrom(target.getClass())) {
// Already intercepted, just return the target.
return target;
} else {
return createProxy(getAllInterfacesThroughDeriveChain(target.getClass()),
new FakeClientBinderHandler(target, mBinderInvocationHandler));
}
}
@SuppressWarnings("unchecked")
@Override
protected void inject(IBinder decorated) throws Throwable {
final Map<String, IBinder> sCache = (Map<String, IBinder>) sSCacheField.get(null);
sCache.put(mServiceName, decorated);
if (Context.ACTIVITY_SERVICE.equals(mServiceName)) {
fixAMSBinderCache(decorated);
} else if (EnvConsts.PACKAGE_MANAGER_SRVNAME.equals(mServiceName)) {View on GitHub (pinned to 1b7ea02c23)
Solutions
- Verify the exact service name against ServiceManager.listServices() on the target device.
- Defer the interception until the service is registered (retry after onServiceRegistered / slight delay via lifecycle, not tight loop).
- Treat a null target as 'nothing to intercept' and skip decoration instead of crashing.
Example fix
// before
IBinder binder = ServiceManager.getService(name); // may be null early
// after
IBinder binder = ServiceManager.getService(name);
if (binder == null) {
// service not yet published; defer interception
return;
} Defensive patterns
Strategy: validation
Validate before calling
IBinder binder = (IBinder) sGetServiceMethod.invoke(null, mServiceName);
if (binder == null) {
// service not published yet: defer interception, do not decorate
return;
} Try / catch
try {
interceptor.decorate(binder);
} catch (IllegalStateException e) {
// target null: retry later when the service is registered
} Prevention
- Check the service exists via ServiceManager.listServices() before intercepting.
- Defer interception until first actual use of the service, not at app start.
- Spell service names exactly as in the framework (e.g. 'activity', 'package').
When it happens
Trigger: fetchTarget() invoking ServiceManager.getService for a service that is not yet published (early boot, service restart) or that does not exist on the device (wrong service name, OEM removed it).
Common situations: Intercepting services during Application attachBaseContext before system services are up; typos in the service name; targeting a service absent on the specific ROM.
Related errors
- Cannot query transaction code of performDexOptSecondary.
- Binder transaction failure.
- fakeBinder does not return fakeInterface, binder: {}, itf: {
- No entries
- libName or context is null!
AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14).
Data as JSON: /api/errors/c3b8d8b64a6217f6.
Report an issue: GitHub.