Skip to content

fix(cli): remove doubled "Expected: Expected" prefix from Flag.choice/primitive errors#5831

Draft
Coly010 wants to merge 4 commits into
developfrom
columferry/cli-1898-flagchoice-error-message-has-a-doubled-expected-expected
Draft

fix(cli): remove doubled "Expected: Expected" prefix from Flag.choice/primitive errors#5831
Coly010 wants to merge 4 commits into
developfrom
columferry/cli-1898-flagchoice-error-message-has-a-doubled-expected-expected

Conversation

@Coly010

@Coly010 Coly010 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

What changed

Any Flag.choice(...)/Flag.choiceWithValue(...)-backed flag (--size on
projects create/branches create, --dns-resolver, --output-format,
--output/-o, --agent) showed a doubled "Expected: Expected ..." prefix
when given an invalid value, e.g.:

Invalid value for flag --size: "nano". Expected: Expected "micro" | "small" | ... , got "nano"

Root cause: several Primitives under effect@4.0.0-beta.93's
effect/unstable/cli (choice — used by Flag.choice/Flag.choiceWithValue
— plus the schema-backed integer, float, boolean, and date) fail with
a raw message that already starts with the word "Expected" (e.g.
`Expected ${validChoices}, got ${value}` for choice, or
Expected a valid date, got Invalid Date for date), and
CliError.InvalidValue's own message getter (CliError.ts:359-364)
independently prepends its own "Expected: " label on top of that —
producing the doubling for any flag or argument backed by one of these
primitives. This is a bug in the vendored effect beta package itself, not
in this repo's code.

Workaround (until upstream effect is fixed) added to the shared CLI
error-formatting layer (subcommand-flag-suggestions.ts), which already
carries similar per-tag rewrites for UnrecognizedOption/UnknownSubcommand:
collapse the literal "Expected: Expected " substring down to a single
"Expected " whenever it appears in an InvalidValue error's rendered
message. Collapsing the exact doubled substring (rather than rebuilding the
surrounding "Invalid value for ..." template ourselves) keeps the fix tied
to the precise defect, covers every affected primitive uniformly, and lets
every other part of the message keep tracking upstream's own wording if it
changes.

Verified against go-parity-auditor: Go's real CLI shows a completely
different message for the same scenario (Error: invalid argument "bogus" for "--size" flag: must be one of [ large | medium | ... ], from
apps/cli-go/internal/utils/enum.go wrapped by cobra/pflag). Full
byte-parity with Go's wording is out of scope here — this ticket is
specifically about the doubled-prefix defect in the TS/Effect-native
message, not a "TS wording differs from Go" report; rewriting every
Flag.choice flag's phrasing to match Go's template would be a separate,
larger change.

Known related (not fixed here)

The underlying Primitive.choice failure text also appends a redundant
, got "X" suffix, so the invalid value still appears twice in the final
message (once right after the flag name, once after "got"). That's a
pre-existing wart in the same vendored effect failure string, not
something this fix introduces, and collapsing it would mean post-processing
effect's expected string further — bigger than this "doubled prefix"
ticket calls for. Left as-is.

Fixes CLI-1898

…/primitive errors

Several `Primitive`s in effect@4.0.0-beta.93's `effect/unstable/cli` (`choice`
-- used by `Flag.choice`/`Flag.choiceWithValue` on `--size`, `--dns-resolver`,
`--output-format`, `--output`/`-o`, `--agent` -- plus the schema-backed
`integer`, `float`, `boolean`, and `date`) fail with a raw message that
already starts with the word "Expected", and `CliError.InvalidValue`'s own
`message` getter independently prepends its own "Expected: " label on top of
that, producing e.g.:

    Invalid value for flag --size: "nano". Expected: Expected "micro" | ... , got "nano"

This is a bug in the vendored `effect` beta package itself, not this repo's
code, so work around it in the shared CLI error-formatting layer
(`subcommand-flag-suggestions.ts`) that already carries similar per-tag
Go-parity rewrites for UnrecognizedOption/UnknownSubcommand: collapse the
literal doubled substring rather than rebuilding the message template
ourselves, so every other part of the message keeps tracking upstream's
wording.

Fixes CLI-1898
@Coly010

Coly010 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@Coly010

This comment was marked as off-topic.

@Coly010 Coly010 self-assigned this Jul 8, 2026
@Coly010

Coly010 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@Coly010

Coly010 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a294658cfc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/shared/cli/subcommand-flag-suggestions.ts Outdated
…rror.message (review: #PRRT_kwDOErm0O86PVbq8)

error.message interpolates the user-controlled error.value twice (once
directly, once again inside error.expected's "got <value>" suffix), so a
message-wide, first-occurrence string replace could target a doubled
"Expected: Expected " substring embedded in the value itself instead of
the real doubled prefix from the primitive parser, silently mangling the
user's input and leaving the actual bug unfixed. Detect and strip the
doubled prefix from error.expected directly and rebuild the message from
CliError.InvalidValue's own template instead.
@Coly010

Coly010 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e6be301da9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/shared/cli/subcommand-flag-suggestions.ts Outdated
…ags (review: #PRRT_kwDOErm0O86PV7Le)

GlobalFlag.setting flags (--output-format, and the legacy --output/-o,
--dns-resolver, --agent) are validated by Command.runWith in a step that
runs after the ShowHelp bundling, so a bad value never reaches
CliOutput.Formatter/formatCliErrorsForDisplay -- it surfaces as a raw
CliError.InvalidValue through runCli's catch-all instead, where
normalize-error.ts read error.message directly and still showed the
doubled "Expected: Expected" prefix.

Extract the doubled-prefix workaround into a shared
invalid-value-message.ts helper and apply it from normalize-error.ts's
mappedError too, so both paths render the same way. Verified by tracing
effect's Command.runWith (Setting flags parsed at step 7, outside the
step-4 ShowHelp path) and reproducing directly: `--output-format bogus`,
`--dns-resolver bogus`, `--agent bogus`, and legacy `-o bogus` all showed
the doubled prefix before this change and a single "Expected" after.
@Coly010

Coly010 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3d843e536a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/shared/output/normalize-error.ts Outdated
…iew: #PRRT_kwDOErm0O86PWZlY)

`value` on `CliError.InvalidValue` is the raw argv token the user typed and
can legitimately be empty or carry surrounding whitespace (e.g.
`--output-format ''` or `--output-format ' json'`). Reading it through the
trim-and-reject-empty `readString` helper either dropped the rewrite
entirely (leaking the original doubled "Expected: Expected" message for
empty values) or silently reported a different value than what was typed.
Added `readRawString` and used it only for `value`; `option`/`expected`/
`kind` stay on `readString` since those are Effect/CLI-generated, never
user input.
@Coly010

Coly010 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit: cff55253dd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant