Skip to content

unstable/cli: excess positional arguments are silently discarded instead of failing #6594

Description

@chenxin-yan

Version: effect 4.0.0-beta.101

What happens

The parser silently drops positional arguments that no declared param consumes, and no combinator can make it fail:

import { Command, Argument } from "effect/unstable/cli"

// Command with no arguments:
const init = Command.make("init", {})
// `mycli init extra` succeeds — "extra" is silently ignored

// Command with a single positional:
const run = Command.make("run", { prompt: Argument.string("prompt") })
// `mycli run "hi" oops` succeeds with prompt = "hi" — "oops" is silently ignored

// Cardinality combinators don't help:
Argument.string("prompt").pipe(Argument.between(1, 1)) // or atMost(1)
// max only stops consuming; the extra positional is still silently dropped

Cause

  • internal/command.js parseParams threads currentArguments through each declared param and discards whatever remains after the loop — there is no "unexpected argument" check.
  • Param.js parsePositionalVariadic enforces min with an error but treats max purely as a stop-consuming bound.

Why this looks like a bug

  • Asymmetric with flags: unknown flags raise UnrecognizedOption, and parseOptionVariadic fails with InvalidValue when occurrences exceed max — positionals do neither.
  • Regression from v3: stable @effect/cli documented a ValidationError for excess arguments.

Suggested fix

Fail the parse when positionals remain unconsumed after parseParams, and/or make positional max reject extras the way flag max does.

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