shwenzhang/AndResGuard · error · ParameterException

Min API Level ( ) > max API Level ( )

Error message

Min API Level (<minSdkVersion>) > max API Level (<maxSdkVersion>)

What it means

Consistency validation in ApkSignerTool.sign: the --min-sdk-version parsed to a larger value than --max-sdk-version, an impossible API range. Fires when the user passes flags in the wrong order or mixed numeric formats, e.g. --min-sdk-version 28 --max-sdk-version 24; no signatures can target an empty version range.

Solutions

  1. Swap the values so min <= max
  2. Raise --max-sdk-version above --min-sdk-version
  3. Drop one of the flags to use defaults (min 1, max unlimited)

Example fix

// before
apksigner sign --min-sdk-version 28 --max-sdk-version 24 --ks ks.jks app.apk
// after
apksigner sign --min-sdk-version 24 --max-sdk-version 28 --ks ks.jks app.apk
Defensive patterns

Strategy: validation

Validate before calling

int min = getFlagInt(args, "--min-sdk-version", 1);
int max = getFlagInt(args, "--max-sdk-version", Integer.MAX_VALUE);
if (min > max) throw new IllegalArgumentException("min-sdk-version (" + min + ") must be <= max-sdk-version (" + max + ")");

Try / catch

try { signCmd(args); } catch (ParameterException e) { System.err.println("Invalid SDK range: " + e.getMessage()); exit(1); }

Prevention

When it happens

Trigger: `apksigner sign --min-sdk-version 28 --max-sdk-version 24 ...` — an inverted or contradictory version range.

Common situations: Copy-pasting min/max values into the wrong flags; build config where minSdk > maxSdk due to edited gradle-derived values; changing --max-sdk-version without lowering min.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of shwenzhang/AndResGuard@e4df245d82 (2026-09-12). Data as JSON: /api/errors/c5bf304447c63ed4. Report an issue: GitHub.

Appendix: source

Thrown at AndResGuard-core/src/main/java/apksigner/ApkSignerTool.java:211

    params = optionsParser.getRemainingParams();
    if (inputApk != null) {
      // Input APK has been specified via preceding parameters. We don't expect any more
      // parameters.
      if (params.length > 0) {
        throw new ParameterException("Unexpected parameter(s) after " + optionOriginalForm + ": " + params[0]);
      }
    } else {
      // Input APK has not been specified via preceding parameters. The next parameter is
      // supposed to be the path to input APK.
      if (params.length < 1) {
        throw new ParameterException("Missing input APK");
      } else if (params.length > 1) {
        throw new ParameterException("Unexpected parameter(s) after input APK (" + params[1] + ")");
      }
      inputApk = new File(params[0]);
    }
    if ((minSdkVersionSpecified) && (minSdkVersion > maxSdkVersion)) {
      throw new ParameterException("Min API Level (" + minSdkVersion + ") > max API Level (" + maxSdkVersion + ")");
    }

    List<ApkSigner.SignerConfig> signerConfigs = new ArrayList<>(signers.size());
    int signerNumber = 0;
    try (PasswordRetriever passwordRetriever = new PasswordRetriever()) {
      for (SignerParams signer : signers) {
        signerNumber++;
        signer.name = "signer #" + signerNumber;
        try {
          signer.loadPrivateKeyAndCerts(passwordRetriever);
        } catch (ParameterException e) {
          System.err.println("Failed to load signer \"" + signer.name + "\": " + e.getMessage());
          System.exit(2);
          return;
        } catch (Exception e) {
          System.err.println("Failed to load signer \"" + signer.name + "\"");
          e.printStackTrace();
          System.exit(2);

View on GitHub (pinned to e4df245d82)