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.
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.
- AssetManager add SharedLibrary Fail
- Cannot query transaction code of performDexOptSecondary.
- checkResInstall failed
AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14).
Data as JSON: /api/errors/0be86660cc3f6361.
Report an issue: GitHub.
Appendix: 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)