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

  1. Fix the custom VersionPolicy to only set selection to SelectionResult.Selection.NONE, .LOCAL, or .REMOTE
  2. Use the built-in policies (PREFER_REMOTE, PREFER_HIGHEST_OR_LOCAL, PREFER_LOCAL) instead of custom ones
  3. Ensure SelectionResult.selection is always explicitly assigned before returning it from selectModule
  4. 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

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


AI-assisted analysis of microg/GmsCore@157c9d86ac (2026-09-06). Data as JSON: /api/errors/b1b5e335d6263ab4. Report an issue: GitHub.