Skip to content

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

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions