What happened
During blue setup, the Control API URL prompt only re-prompts for syntactic problems. A
well-formed but wrong URL passes the prompt's .validate() closure, then fails at the discovery
step, and the whole command exits with status 1. Typo the hostname or pick the wrong deployment
and you have to re-run blue setup from the top instead of just correcting the URL.
Expected: a failed discovery should report the error and let me enter a different URL (with an
explicit way to cancel out), the way malformed input already does.
Steps to reproduce
blue setup
- At
Control API URL, enter a well-formed HTTPS URL that isn't a Blue deployment — e.g.
https://harnes.example.com (typo'd host) or a host with no /.well-known/metaharness.
- The
Discovering deployment… spinner fails, the error prints, and the process exits 1.
- There is no way to retry without starting
blue setup over.
Where it happens
crates/gh-cli/src/commands.rs:79-96 — prompt_control_api_url(). The .validate() closure
(:89) calls gh_service::validate_deployment_url, which only checks parse/host/HTTPS/no
credentials-query-fragment (crates/gh-service/src/discovery.rs:29-50). Those failures do
re-prompt correctly.
crates/gh-cli/src/commands.rs:98-117 — discover_configuration() runs after the prompt has
returned and bubbles the error up.
crates/gh-service/src/discovery.rs:52-76 — discover() errors on DNS/TLS/timeout (:64),
non-2xx (:65-70), invalid JSON (:71-73), and invalid discovery document
(validate_document, :78-101).
- Call sites that die:
commands.rs:302 (setup()) and commands.rs:729 (first-run path in
start(), i.e. bare blue with no blue.toml).
- Exit:
crates/gh-cli/src/main.rs:177-180 → print_error(&e); std::process::exit(1).
Suggested fix
Wrap prompt + discovery in a retry loop used by both call sites (commands.rs:302 and
commands.rs:729): on discovery failure, show the error via cliclack::log::error, then re-prompt
for a different URL — either directly or gated on a cliclack::confirm("Try a different URL?"),
mirroring retry_gateway_setup (commands.rs:1100-1124). Declining should outro_cancel and exit
the way the existing cancel paths do (commands.rs:380-383). Keep the non-TTY bail! guard at
commands.rs:80-84 so automation still fails fast on the first error, and consider capping retries.
There is also an in-repo precedent for the loop shape itself at commands.rs:3254-3283
(loop { … cliclack::select … }, re-prompt until valid or cancel).
Blue version
main @ e596c5d
OS / environment
Any (logic is platform-independent; observed reading the source).
What happened
During
blue setup, the Control API URL prompt only re-prompts for syntactic problems. Awell-formed but wrong URL passes the prompt's
.validate()closure, then fails at the discoverystep, and the whole command exits with status 1. Typo the hostname or pick the wrong deployment
and you have to re-run
blue setupfrom the top instead of just correcting the URL.Expected: a failed discovery should report the error and let me enter a different URL (with an
explicit way to cancel out), the way malformed input already does.
Steps to reproduce
blue setupControl API URL, enter a well-formed HTTPS URL that isn't a Blue deployment — e.g.https://harnes.example.com(typo'd host) or a host with no/.well-known/metaharness.Discovering deployment…spinner fails, the error prints, and the process exits 1.blue setupover.Where it happens
crates/gh-cli/src/commands.rs:79-96—prompt_control_api_url(). The.validate()closure(
:89) callsgh_service::validate_deployment_url, which only checks parse/host/HTTPS/nocredentials-query-fragment (
crates/gh-service/src/discovery.rs:29-50). Those failures dore-prompt correctly.
crates/gh-cli/src/commands.rs:98-117—discover_configuration()runs after the prompt hasreturned and bubbles the error up.
crates/gh-service/src/discovery.rs:52-76—discover()errors on DNS/TLS/timeout (:64),non-2xx (
:65-70), invalid JSON (:71-73), and invalid discovery document(
validate_document,:78-101).commands.rs:302(setup()) andcommands.rs:729(first-run path instart(), i.e. barebluewith noblue.toml).crates/gh-cli/src/main.rs:177-180→print_error(&e); std::process::exit(1).Suggested fix
Wrap prompt + discovery in a retry loop used by both call sites (
commands.rs:302andcommands.rs:729): on discovery failure, show the error viacliclack::log::error, then re-promptfor a different URL — either directly or gated on a
cliclack::confirm("Try a different URL?"),mirroring
retry_gateway_setup(commands.rs:1100-1124). Declining shouldoutro_canceland exitthe way the existing cancel paths do (
commands.rs:380-383). Keep the non-TTYbail!guard atcommands.rs:80-84so automation still fails fast on the first error, and consider capping retries.There is also an in-repo precedent for the loop shape itself at
commands.rs:3254-3283(
loop { … cliclack::select … }, re-prompt until valid or cancel).Blue version
main@e596c5dOS / environment
Any (logic is platform-independent; observed reading the source).