microg/GmsCore · error · DynamiteModule.LoadingException
VersionPolicy returned invalid code:
Error message
VersionPolicy returned invalid code:
What it means
DynamiteModule.load switches on the VersionPolicy.SelectionResult.selection value. If a policy returns a selection code that is not NONE, LOCAL, or REMOTE, the default branch throws LoadingException('VersionPolicy returned invalid code:'). This indicates a buggy or incompatible custom VersionPolicy.
Source
Thrown at play-services-basement/src/main/java/com/google/android/gms/dynamite/DynamiteModule.java:146
}
@NonNull
public static DynamiteModule load(@NonNull Context context, @NonNull VersionPolicy policy, @NonNull String moduleId) throws LoadingException {
Context applicationContext = context.getApplicationContext();
if (applicationContext == null) throw new LoadingException("null application Context", null);
try {
VersionPolicy.SelectionResult result = policy.selectModule(context, moduleId, VersionPolicy.IVersions.Default);
Log.i(TAG, "Considering local module " + moduleId + ":" + result.localVersion + " and remote module " + moduleId + ":" + result.remoteVersion);
switch (result.selection) {
case NONE:
throw new LoadingException("No acceptable module " + moduleId + " found. Local version is " + result.localVersion + " and remote version is " + result.remoteVersion + ".");
case LOCAL:
Log.i(TAG, "Selected local version of " + moduleId);
return new DynamiteModule(context);
case REMOTE:
throw new UnsupportedOperationException();
default:
throw new LoadingException("VersionPolicy returned invalid code:" + result.selection);
}
} catch (LoadingException loadingException) {
throw loadingException;
} catch (Throwable e) {
throw new LoadingException("Failed to load remote module.", e);
}
}
@NonNull
public IBinder instantiate(@NonNull String className) throws LoadingException {
try {
return (IBinder) this.moduleContext.getClassLoader().loadClass(className).newInstance();
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | RuntimeException e) {
throw new LoadingException("Failed to instantiate module class: " + className, e);
}
}
}
View on GitHub (pinned to 157c9d86ac)
Solutions
- Fix the custom VersionPolicy to only set selection to SelectionResult.Selection.NONE, .LOCAL, or .REMOTE
- Use the built-in policies (PREFER_REMOTE, PREFER_HIGHEST_OR_LOCAL, PREFER_LOCAL) instead of custom ones
- Ensure SelectionResult.selection is always explicitly assigned before returning it from selectModule
- Catch LoadingException and fall back to default module-loading behavior
Example fix
// before result.selection = 7; // unknown code -> throws // after result.selection = VersionPolicy.SelectionResult.Selection.LOCAL;
Defensive patterns
Strategy: validation
Validate before calling
// if you supply a custom policy, assert its output before load
VersionPolicy.SelectionResult r = policy.selectModule(ctx, moduleId, versions);
boolean ok = r.selection == VersionPolicy.SelectionResult.Selection.NONE
|| r.selection == VersionPolicy.SelectionResult.Selection.LOCAL
|| r.selection == VersionPolicy.SelectionResult.Selection.REMOTE;
if (!ok) { /* fix policy, don't call load */ } Try / catch
try {
DynamiteModule m = DynamiteModule.load(ctx, myPolicy, moduleId);
} catch (DynamiteModule.LoadingException e) {
// invalid selection code — switch to a built-in policy
m = DynamiteModule.load(ctx, DynamiteModule.PREFER_HIGHEST_OR_LOCAL, moduleId);
} Prevention
- Only return NONE/LOCAL/REMOTE from custom VersionPolicies
- Always initialize SelectionResult.selection before returning
- Prefer built-in VersionPolicy constants over hand-rolled implementations
- Keep gms library versions consistent so policy enums match
When it happens
Trigger: Supplying a custom VersionPolicy (or a SelectionResult built by one) that sets an out-of-range/unknown selection constant; version mismatch where a policy written against a different library version returns an unrecognized code.
Common situations: Hand-rolled VersionPolicy implementations copied from older gms versions; mocked SelectionResult in tests with an unset/garbage selection field; binary-incompatible library versions.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- null application Context
- No acceptable module " + moduleId + " found. Local version i
- granularity {granularity} must be a Granularity.GRANULARITY_
- priority {priority} must be a Priority.PRIORITY_* constant
- throttle behavior {throttleBehavior} must be a ThrottleBehav
AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06).
Data as JSON: /api/errors/b1b5e335d6263ab4.
Report an issue: GitHub.