Skip to content

Subcommand parameters in ArgGroup result in ArithmeticException #1213

@LorenKeagle

Description

@LorenKeagle

If I define a parameter list in an ArgGroup in a subcommand class, PicoCLI always throws an exception when any parameters are provided. Here is how my ArgGroup is specified in my subcommand:

    @ArgGroup(exclusive = false, validate = false, heading = "scan source options%n")
    SourceOptions sourceOptions;

    static class SourceOptions {

        @Parameters(paramLabel = "FILE")
        List<File> reportFiles;

        @Option(names = {"-b", "--build-id"}, paramLabel = "Build ID")
        List<Integer> buildIds;

        @Option(names = {"-a", "--app-name"}, paramLabel = "App Name")
        List<String> appNames;
   }

The user can specify any number of files, but can also optionally specify inputs using some attributes (build-id and app-name above). The ArgGroup is only being used to group options in the Help/Usage output.

If any parameters are provided on the commandline, I get the following exception:

picocli.CommandLine$ParameterException: ArithmeticException: / by zero while processing argument at or before arg[0] 'analyze' in [analyze, x, y, z]: java.lang.ArithmeticException: / by zero
	at picocli.CommandLine$ParameterException.create(CommandLine.java:17091)
	at picocli.CommandLine$ParameterException.access$18500(CommandLine.java:17015)
	at picocli.CommandLine$Interpreter.parse(CommandLine.java:12367)
	at picocli.CommandLine$Interpreter.processSubcommand(CommandLine.java:12623)
	at picocli.CommandLine$Interpreter.processArguments(CommandLine.java:12537)
	at picocli.CommandLine$Interpreter.parse(CommandLine.java:12358)
	at picocli.CommandLine$Interpreter.parse(CommandLine.java:12243)
	at picocli.CommandLine.parseArgs(CommandLine.java:1458)
	at picocli.CommandLine.execute(CommandLine.java:2057)
	at com.imperva.AutoTune.AutoTune.main(AutoTune.java:150)
Caused by: java.lang.ArithmeticException: / by zero
	at picocli.CommandLine$ParseResult$GroupMatchContainer.canMatchPositionalParam(CommandLine.java:11962)
	at picocli.CommandLine$Interpreter.processPositionalParameter(CommandLine.java:12673)
	at picocli.CommandLine$Interpreter.processArguments(CommandLine.java:12600)
	at picocli.CommandLine$Interpreter.parse(CommandLine.java:12358)
	... 7 more

Here is some more detailed TRACE output:

$ java -Dpicocli.trace=DEBUG -jar build/libs/AutoTune-0.5.0.jar analyze x y z
[picocli DEBUG] Creating CommandSpec for com.foo.AutoTune.AutoTune@1c655221 with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Creating CommandSpec for class com.foo.AutoTune.AnalyzeEvents with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Getting a com.foo.AutoTune.AnalyzeEvents instance from factory picocli.CommandLine$DefaultFactory@5594a1b5
[picocli DEBUG] Factory returned a com.foo.AutoTune.AnalyzeEvents instance (6a5fc7f7)
[picocli DEBUG] Adding subcommand 'analyze-events' to 'AutoTune'
[picocli DEBUG] Adding alias 'events' for 'AutoTune'
[picocli DEBUG] Adding alias 'ev' for 'AutoTune'
[picocli DEBUG] Creating CommandSpec for class com.foo.AutoTune.Process with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Getting a com.foo.AutoTune.Process instance from factory picocli.CommandLine$DefaultFactory@5594a1b5
[picocli DEBUG] Factory returned a com.foo.AutoTune.Process instance (21bcffb5)
[picocli DEBUG] Adding subcommand 'analyze-scan' to 'AutoTune'
[picocli DEBUG] Adding alias 'analyze' for 'AutoTune'
[picocli DEBUG] Adding alias 'as' for 'AutoTune'
[picocli DEBUG] Creating CommandSpec for class picocli.CommandLine$HelpCommand with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] Adding subcommand 'help' to 'AutoTune'
[picocli INFO] Setting exclusive=false because [[-s=FILE] [--generate-settings=FILE]] is a non-validating group.
[picocli DEBUG] Creating CommandSpec for picocli.CommandLine$AutoHelpMixin@531be3c5 with factory picocli.CommandLine$DefaultFactory
[picocli DEBUG] getTerminalWidth() executing command [tput, cols]
[picocli DEBUG] getTerminalWidth() parsing output:  238
[picocli DEBUG] getTerminalWidth() returning: 238 in 27.4ms
[picocli INFO] Picocli version: 4.5.1, JVM: 14.0.1 (N/A OpenJDK 64-Bit Server VM 14.0.1+14), OS: Mac OS X 10.15.7 x86_64
[picocli INFO] Parsing 4 command line args [analyze, x, y, z]
[picocli DEBUG] Parser configuration: optionsCaseInsensitive=false, subcommandsCaseInsensitive=false, abbreviatedOptionsAllowed=false, abbreviatedSubcommandsAllowed=false, aritySatisfiedByAttachedOptionParam=false, atFileCommentChar=#, caseInsensitiveEnumValuesAllowed=false, collectErrors=false, endOfOptionsDelimiter=--, expandAtFiles=true, limitSplit=false, overwrittenOptionsAllowed=false, posixClusteredShortOptionsAllowed=true, separator=null, splitQuotedStrings=false, stopAtPositional=false, stopAtUnmatched=false, toggleBooleanFlags=false, trimQuotes=false, unmatchedArgumentsAllowed=false, unmatchedOptionsAllowedAsOptionParameters=true, unmatchedOptionsArePositionalParams=false, useSimplifiedAtFiles=false
[picocli DEBUG] (ANSI is enabled by default: systemproperty[picocli.ansi]=null, isatty=true, TERM=xterm-256color, OSTYPE=null, isWindows=false, JansiConsoleInstalled=false, ANSICON=null, ConEmuANSI=null, NO_COLOR=null, CLICOLOR=null, CLICOLOR_FORCE=null)
[picocli DEBUG] Initializing command 'AutoTune' (user object: com.foo.AutoTune.AutoTune@1c655221): 9 options, 0 positional parameters, 0 required, 2 groups, 7 subcommands.
[picocli DEBUG] Set initial value for field java.io.File com.foo.AutoTune.AutoTune.configFile of type class java.io.File to null.
[picocli DEBUG] Set initial value for field String com.foo.AutoTune.AutoTune.configVersion of type class java.lang.String to null.
[picocli DEBUG] Initial value not available for method void com.foo.AutoTune.AutoTune.setVerbose(boolean[])
[picocli DEBUG] Set initial value for field boolean picocli.CommandLine$AutoHelpMixin.helpRequested of type boolean to false.
[picocli DEBUG] Set initial value for field boolean picocli.CommandLine$AutoHelpMixin.versionRequested of type boolean to false.
[picocli DEBUG] [0] Processing argument 'analyze'. Remainder=[x, y, z]
[picocli DEBUG] Found subcommand 'analyze' (command 'analyze-scan' (user object: com.foo.AutoTune.Process@21bcffb5))
[picocli DEBUG] Checking required args for parent command 'AutoTune' (user object: com.foo.AutoTune.AutoTune@1c655221)...
[picocli DEBUG] Initializing command 'analyze-scan' (user object: com.foo.AutoTune.Process@21bcffb5): 13 options, 1 positional parameters, 0 required, 2 groups, 0 subcommands.
[picocli DEBUG] Set initial value for field boolean com.foo.AutoTune.Process.analyzeAutoMitigate of type boolean to false.
[picocli DEBUG] Not applying initial value for inherited option '--config'
[picocli DEBUG] Not applying initial value for inherited option '--edit-in-place'
[picocli DEBUG] Not applying initial value for inherited option '--output-config'
[picocli DEBUG] Not applying initial value for inherited option '--config-version'
[picocli DEBUG] Not applying initial value for inherited option '--settings'
[picocli DEBUG] Not applying initial value for inherited option '--generate-settings'
[picocli DEBUG] Not applying initial value for inherited option '--verbose'
[picocli DEBUG] [1] Processing argument 'x'. Remainder=[y, z]
[picocli DEBUG] 'x' cannot be separated into <option>=<option-parameter>
[picocli DEBUG] Could not find option 'x', deciding whether to treat as unmatched option or positional parameter...
[picocli DEBUG] No option named 'x' found. Processing as positional parameter
[picocli DEBUG] Single-character arguments that don't match known options are considered positional parameters
[picocli DEBUG] [1] Processing next arg as a positional parameter. Command-local position=0. Remainder=[x, y, z]
[picocli INFO] Adding match to GroupMatchContainer [[FILE...] [-b=Build ID]... [-a=App Name]...]={} (group=1 [[FILE...] [-b=Build ID]... [-a=App Name]...]).
[picocli DEBUG] Creating new user object of type class com.foo.AutoTune.Process$SourceOptions for group [[FILE...] [-b=Build ID]... [-a=App Name]...]
[picocli DEBUG] Created com.foo.AutoTune.Process$SourceOptions@48eff760, invoking setter FieldBinding(com.foo.AutoTune.Process$SourceOptions com.foo.AutoTune.Process.analyzeSource) with scope com.foo.AutoTune.Process@21bcffb5
[picocli DEBUG] Initializing params[0..*] in group [[FILE...] [-b=Build ID]... [-a=App Name]...]: setting scope to user object com.foo.AutoTune.Process$SourceOptions@48eff760 and initializing initial and default values
[picocli DEBUG] Set initial value for field java.io.File[] com.foo.AutoTune.Process$SourceOptions.analyzeReportFiles of type class [Ljava.io.File; to null.
[picocli DEBUG] defaultValue not defined for field java.io.File[] com.foo.AutoTune.Process$SourceOptions.analyzeReportFiles
[picocli DEBUG] Initializing --build-id=Build ID in group [[FILE...] [-b=Build ID]... [-a=App Name]...]: setting scope to user object com.foo.AutoTune.Process$SourceOptions@48eff760 and initializing initial and default values
[picocli DEBUG] Set initial value for field java.util.List<Integer> com.foo.AutoTune.Process$SourceOptions.analyzeBuildIds of type interface java.util.List to null.
[picocli DEBUG] defaultValue not defined for field java.util.List<Integer> com.foo.AutoTune.Process$SourceOptions.analyzeBuildIds
[picocli DEBUG] Initializing --app-name=App Name in group [[FILE...] [-b=Build ID]... [-a=App Name]...]: setting scope to user object com.foo.AutoTune.Process$SourceOptions@48eff760 and initializing initial and default values
[picocli DEBUG] Set initial value for field java.util.List<String> com.foo.AutoTune.Process$SourceOptions.analyzeAppNames of type interface java.util.List to null.
[picocli DEBUG] defaultValue not defined for field java.util.List<String> com.foo.AutoTune.Process$SourceOptions.analyzeAppNames
[picocli DEBUG] Initialization complete for group [[FILE...] [-b=Build ID]... [-a=App Name]...]
ArithmeticException: / by zero while processing argument at or before arg[0] 'analyze' in [analyze, x, y, z]: java.lang.ArithmeticException: / by zero
[picocli DEBUG] getTerminalWidth() executing command [tput, cols]
[picocli DEBUG] getTerminalWidth() parsing output:  238
[picocli DEBUG] getTerminalWidth() returning: 238 in 26.1ms

I resolved the exception by removing the ArgGroup from the subcommand. It would be nice to know if there is a way to make this work.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions