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

  1. Pass the correct ClassLoader to readParcelable/readParcelableCreator
  2. Keep the class name stable across versions (add @Keep / proguard keep rule)
  3. Restore the renamed/removed class or migrate the persisted data format
  4. 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

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


AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12). Data as JSON: /api/errors/61e0481415bc2cfe. Report an issue: GitHub.