Skip to content

Invalid error when parsing a sub command with only one parameter fixed with the 'ExactlyOnce' attribute. #216

@bryjen

Description

@bryjen

Description

Attempting to parse a sub command with only one parameter fixed with the ExactlyOnce attribute errors even though the correct format is provided.

Repro steps

open Argu

type Arguments =
    | [<First; CliPrefix(CliPrefix.None)>] Item_Group of ParseResults<SubArguments>
    
    interface IArgParserTemplate with
        member this.Usage =
            match this with
            | Item_Group _ -> "Specifies an item group."
            
and SubArguments =
    | [<ExactlyOnce>] Path of path:string list
    
    interface IArgParserTemplate with
        member this.Usage =
            match this with
            | Path _ -> "Some path."

Expected behavior

Suppose we have the following main function and input as the program args: item-group --path elem1 elem2

[<EntryPoint>]
let main argv =
    let parser = ArgumentParser.Create<Arguments>(errorHandler = ExceptionExiter())
    
    try
        let parseResults = parser.ParseCommandLine () 
        printfn $"%A{parseResults}"
    with
        | ex -> printfn $"%s{ex.Message}"
    0

Since only one of the path parameters was provided, it is expected to parse normally with the following output:

[Item_Group [Path ["elem1"; "elem2"]]]

Actual behavior

Instead, it errors, indicating that the '--path' parameter is missing despite being provided.

ERROR: missing parameter '--path'.
USAGE: ConsoleApplication.exe item-group [--help] --path [<path>...]

OPTIONS:

    --path [<path>...]    Some path.
    --help                display this list of options.

It has the following stack trace:

   at Argu.ExceptionExiter.Argu.IExiter.Exit[a](String msg, ErrorCode errorCode) in /_//src/Argu/Types.fs:line 63
   at Argu.ArgumentParser`1.ParseCommandLine(FSharpOption`1 inputs, FSharpOption`1 ignoreMissing, FSharpOption`1 ignoreUnrecognized, FSharpOption`1 raiseOnUsage) in /_//src/Argu/ArgumentParser.fs:line 140
   at Program.main(String[] argv) in C:\###\fsharp_proj\src\ConsoleApplication\Program.fs:line 24

Known workarounds

Maintaining the condition of having the parameter be provided exactly once, a work around is by having another hidden parameter like so:

// ...
and SubArguments =
    | [<Hidden>] Hidden
    | [<ExactlyOnce>] Path of path:string list
    
    interface IArgParserTemplate with
        member this.Usage =
            match this with
            | Hidden -> "" 
            | Path _ -> "Some path."

Parsing then works as expected, with the constraint (exactly once) being enforced as well.

Related information

  • Bug seems to be independent of the type of the parameter (errors for ints, bools, strings, etc. + lists).
  • Bug seems to be a problem with attributes.
    | Path of path:string list    // Does NOT error
    | [<Unique>] Path of path:string list    // Does NOT error
    | [<Mandatory>] Path of path:string list    // ERRORS
    | [<Mandatory; Unique>] Path of path:string list    // ERRORS
  • Win 11 (Version 22H2)
  • Argu Release 6.1.4
  • .NET 7.0.401

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions