MuntashirAkon/AppManager · error · BadParcelableException
ClassNotFoundException when unmarshalling: " + name
Error message
ClassNotFoundException when unmarshalling: " + name
What it means
ParcelUtils.readParcelableCreator loads the class named in the Parcel with Class.forName. If the class cannot be found on the given (or default) ClassLoader, the ClassNotFoundException is logged and rethrown as BadParcelableException.
Source
Thrown at libcore/io/src/main/java/aosp/android/content/pm/ParcelUtils.java:85
throw new BadParcelableException("Parcelable protocol requires "
+ "the CREATOR object to be static on class " + name);
}
Class<?> creatorType = f.getType();
if (!Parcelable.Creator.class.isAssignableFrom(creatorType)) {
// Fail before calling Field.get(), not after, to avoid initializing
// parcelableClass unnecessarily.
throw new BadParcelableException("Parcelable protocol requires a "
+ "Parcelable.Creator object called "
+ "CREATOR on class " + name);
}
creator = (Parcelable.Creator<?>) f.get(null);
} catch (IllegalAccessException e) {
Log.e(TAG, "Illegal access when unmarshalling: " + name, e);
throw new BadParcelableException(
"IllegalAccessException when unmarshalling: " + name);
} catch (ClassNotFoundException e) {
Log.e(TAG, "Class not found when unmarshalling: " + name, e);
throw new BadParcelableException("ClassNotFoundException when unmarshalling: " + name);
} catch (NoSuchFieldException e) {
throw new BadParcelableException("Parcelable protocol requires a "
+ "Parcelable.Creator object called "
+ "CREATOR on class " + name);
}
if (creator == null) {
throw new BadParcelableException("Parcelable protocol requires a "
+ "non-null Parcelable.Creator object called "
+ "CREATOR on class " + name);
}
map.put(name, creator);
}
}
return creator;
}
}
View on GitHub (pinned to 0152f468fc)
Solutions
- Pass the correct ClassLoader to readParcelable/readParcelableCreator
- Keep the class name stable across versions (add @Keep / proguard keep rule)
- Restore the renamed/removed class or migrate the persisted data format
- Ensure both IPC sides share the same parcelable class package+name
Example fix
// before Parcelable p = ParcelUtils.readParcelable(parcel, null); // after Parcelable p = ParcelUtils.readParcelable(parcel, MyData.class.getClassLoader());
Defensive patterns
Strategy: try-catch
Validate before calling
boolean classExists(String name, ClassLoader loader) {
try { Class.forName(name, false, loader); return true; }
catch (ClassNotFoundException e) { return false; }
} Try / catch
try {
T p = ParcelUtils.readParcelable(parcel, loader);
} catch (BadParcelableException e) {
if (e.getCause() instanceof ClassNotFoundException) {
Log.e(TAG, "Unknown parcelable class — version skew or missing keep rule", e);
}
} Prevention
- Always pass an explicit ClassLoader (e.g. the app's, not null) when crossing classloader boundaries
- Keep parcelable class names stable; use @Keep
- Migrate/validate persisted bundles after refactors
When it happens
Trigger: The Parcel contains a class name that is absent at read time: app refactor/renamed class, proguard obfuscation, reading a parcel written by a different app/process whose class isn't on the local classpath, or a wrong loader passed in.
Common situations: Restoring persisted bundles after upgrading/refactoring; cross-app IPC with private classes; R8 renaming without keep rules; classloader differences (plugin/dynamic feature classloaders).
Related errors
- Can't unparcel type " + actual.getName() + " in list of type
- Parcelable protocol requires that the class implements Parce
- Parcelable protocol requires a Parcelable.Creator object cal
- Parcelable protocol requires a non-null Parcelable.Creator o
- Parcelable protocol requires the CREATOR object to be static
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/61e0481415bc2cfe.
Report an issue: GitHub.