Tencent/tinker · error · IllegalStateException
resource references is null
Error message
resource references is null
What it means
To inject patched resources, Tinker enumerates every live Resources instance via ActivityThread's internal registry (mResourceImpls on N+, mActiveResources on older versions). This IllegalStateException means both lookups yielded null, so there is no known set of Resources objects to patch and the resource patch cannot be applied.
Source
Thrown at tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/TinkerResourcePatcher.java:167
final Field mResourceReferences = findField(resourcesManagerClass, "mResourceReferences");
references = (Collection<WeakReference<Resources>>) mResourceReferences.get(resourcesManager);
try {
final Field mResourceImplsField = findField(resourcesManagerClass, "mResourceImpls");
resourceImpls = (Map<Object, WeakReference<Object>>) mResourceImplsField.get(resourcesManager);
} catch (Throwable ignored) {
resourceImpls = null;
}
}
} else {
final Field fMActiveResources = findField(activityThread, "mActiveResources");
final HashMap<?, WeakReference<Resources>> activeResources7 =
(HashMap<?, WeakReference<Resources>>) fMActiveResources.get(currentActivityThread);
references = activeResources7.values();
}
// check resource
if (references == null) {
throw new IllegalStateException("resource references is null");
}
final Resources resources = context.getResources();
// fix jianGuo pro has private field 'mAssets' with Resource
// try use mResourcesImpl first
if (SDK_INT >= 24) {
try {
// N moved the mAssets inside an mResourcesImpl field
resourcesImplFiled = findField(resources, "mResourcesImpl");
} catch (Throwable ignore) {
// for safety
assetsFiled = findField(resources, "mAssets");
}
} else {
assetsFiled = findField(resources, "mAssets");
}
View on GitHub (pinned to 1b7ea02c23)
Solutions
- Update Tinker to a version supporting the device's Android release.
- Reproduce on the exact device/ROM, dump ActivityThread fields, and report to Tinker maintainers.
- Disable resource patching (tinker not configured for RES, or only ship DEX patches) if the app can tolerate missing resource fixes on that ROM.
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight on the target device before enabling resource patches
try {
Object at = ShareReflectUtil.getActivityThread(context, null);
ShareReflectUtil.findField(at, SDK_INT >= 24 ? "mResourcesManager" : "mActiveResources");
} catch (Throwable t) {
disableResourcePatchForThisDevice();
} Try / catch
try {
TinkerResourcePatcher.monkeyPatchExistingResources(context, externalResourceFile);
} catch (TinkerRuntimeException e) {
// resource injection unsupported here: continue with dex-only patch
Log.w(TAG, "resource patch skipped: " + e.getMessage());
} Prevention
- Ship resource patches only to device/OS combinations validated in QA.
- Update Tinker promptly when adopting new Android versions.
- Design the app to tolerate missing resource patches (dex patch still applies).
When it happens
Trigger: MonkeyPatchResourcePatcher running on a framework where ActivityThread's resource-registry field was renamed, removed, or typed differently by the OEM; also when reflection to ActivityThread itself failed earlier and the fallback path also found nothing.
Common situations: Non-AOSP or heavily modified ROMs; preview/beta Android versions whose ActivityThread internals differ; devices where hidden-API restrictions block reading these fields.
Related errors
- Fail to hack resourceImpls field.
- failed to fetch instance of ActivityThread.
- zipEntry is null when get from oldApk
- patch %s extract failed (%s).
- createDelegate failed
AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14).
Data as JSON: /api/errors/0be86660cc3f6361.
Report an issue: GitHub.