{"record":{"id":"4b07c0d6385d624c","repo":"shwenzhang/AndResGuard","slug":"valuedescription-mlastoptionoriginalform-must-be-a-decimal","errorCode":null,"errorMessage":"<valueDescription> (<mLastOptionOriginalForm>) must be a decimal number: <value>","messagePattern":"<valueDescription> \\(<mLastOptionOriginalForm>\\) must be a decimal number: <value>","errorType":"validation","errorClass":"OptionsException","httpStatus":null,"severity":"error","filePath":"AndResGuard-core/src/main/java/apksigner/OptionsParser.java","lineNumber":128,"sourceCode":"    String param = mParams[mIndex];\n    if (\"--\".equals(param)) {\n      // End of options marker\n      throw new OptionsException(valueDescription + \" missing after \" + mLastOptionOriginalForm);\n    }\n    mIndex++;\n    return param;\n  }\n\n  /**\n   * Returns the value of the current numeric option, throwing an exception if the value is\n   * missing or is not numeric.\n   */\n  public int getRequiredIntValue(String valueDescription) throws OptionsException {\n    String value = getRequiredValue(valueDescription);\n    try {\n      return Integer.parseInt(value);\n    } catch (NumberFormatException e) {\n      throw new OptionsException(valueDescription\n                                 + \" (\"\n                                 + mLastOptionOriginalForm\n                                 + \") must be a decimal number: \"\n                                 + value);\n    }\n  }\n\n  /**\n   * Gets the value of the current boolean option. Boolean options are not required to have\n   * explicitly specified values.\n   */\n  public boolean getOptionalBooleanValue(boolean defaultValue) throws OptionsException {\n    if (mLastOptionValue != null) {\n      // --option=value form\n      String stringValue = mLastOptionValue;\n      mLastOptionValue = null;\n      if (\"true\".equals(stringValue)) {\n        return true;","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/shwenzhang/AndResGuard/blob/e4df245d82f27d9a2d0dd108260a3510cbaba849/AndResGuard-core/src/main/java/apksigner/OptionsParser.java#L110-L146","documentation":"An option whose value must be an integer (parsed via Integer.parseInt) received a non-decimal value. The parser first fetched the required value successfully, then failed converting it, reporting the offending option, its original form, and the raw value. Typical of options like --min-sdk-version or --v1-signing-scheme variants taking numeric input.","triggerScenarios":"Calling `apksigner sign --min-sdk-version 4.2 ...` or passing values with spaces, plus signs in unexpected places, hex notation (`0x18`), or an empty/non-numeric value where an int option is expected.","commonSituations":"Copying Android API level as a version string (\"7.0\") instead of the numeric API level (24); typos like `24 ` with trailing characters; localization or shell quoting introducing invisible characters; scripts interpolating non-numeric variables into numeric flags.","solutions":["Replace the value with a plain decimal integer (Android API level), e.g. `--min-sdk-version 24` instead of `--min-sdk-version 7.0`.","Trim whitespace and hidden characters from the value, especially in shell scripts: `\"${VAR//[[:space:]]/}\"`.","Convert hex or version strings to decimal API levels before passing them.","Check which option the message names — it points at the exact flag receiving the bad value."],"exampleFix":"// before\napksigner sign --min-sdk-version 7.0 --out app.apk in.apk\n// after\napksigner sign --min-sdk-version 24 --out app.apk in.apk","handlingStrategy":"validation","validationCode":"static String requireDecimal(String option, String value) {\n  if (value == null || !value.matches(\"-?\\\\d+\")) {\n    throw new IllegalArgumentException(option + \" must be a decimal integer (got: \" + value + \")\");\n  }\n  return value.trim();\n}\n// usage before building the command line:\nString minSdk = requireDecimal(\"--min-sdk-version\", System.getenv(\"MIN_SDK\"));","typeGuard":null,"tryCatchPattern":"try {\n  apksignerSign(args);\n} catch (OptionsException e) {\n  if (e.getMessage().contains(\"must be a decimal number\")) {\n    System.err.println(\"Bad numeric flag: \" + e.getMessage()\n        + \" — pass Android API levels as plain integers (e.g. 24, not 7.0).\");\n  }\n  throw e;\n}","preventionTips":["Pass Android API levels (24, 28, 30) rather than version names (7.0, 11).","Sanitize numeric env variables: trim whitespace and strip non-digits before use.","Avoid hex notation (0x18) for numeric flags.","Validate script variables with a regex ^-?\\d+$ before interpolation.","Keep numeric values unquoted-only when the value itself contains no stray characters."],"tags":["cli","number-format","integer-parsing","apksigner"],"backgroundTag":"invalid-argument-format","analyzedSha":"e4df245d82f27d9a2d0dd108260a3510cbaba849","analyzedAt":"2026-09-12T17:49:07.798Z","contentChangedAt":"2026-09-12T17:49:07.798Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}