Skip to content

Commit 500ae11

Browse files
authored
feat(nodeup): standardize actionable error messages with hints (#293)
## Summary - standardize all `NodeupError` messages to `<cause>. Hint: <next action>` - keep JSON error envelope schema stable (`kind`, `message`, `exit_code`) while improving message text - migrate nodeup command/runtime error paths to actionable hints (toolchain/run/show/which/self/installer/release-index/etc.) - update integration tests for new message wording and hint presence - update nodeup docs/contracts/public docs to reflect the new error-message behavior ## Validation - cargo fmt --all - cargo test -p nodeup - cargo test ## Notes - clap-generated parser errors are intentionally unchanged
1 parent 17b2a22 commit 500ae11

21 files changed

Lines changed: 600 additions & 302 deletions

apps/public-docs/nodeup.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ nodeup override set lts --path /path/to/project
6969
- `--output human|json` is available for management commands.
7070
- Human mode uses pretty `tracing` logs by default.
7171
- JSON mode writes machine payloads to stdout and keeps logs off by default unless explicitly enabled.
72+
- Handled failures use an actionable message shape: `<cause>. Hint: <next action>`.
7273
- `completions` always writes raw completion scripts to stdout, even when `--output json` is set.
7374

7475
## Shell completions

crates/nodeup/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ If no selector resolves, commands fail with deterministic `not-found` errors.
5050
- success payloads are written to stdout as JSON
5151
- handled failures are written to stderr as JSON envelopes
5252
- fields: `kind`, `message`, `exit_code`
53+
- `message` follows `<cause>. Hint: <next action>` for actionable recovery guidance
5354
- default logging is off unless explicitly enabled via `RUST_LOG`
5455
- `completions` command:
5556
- always writes raw completion script text to stdout
@@ -102,6 +103,8 @@ cargo test
102103
- verify `<path>/bin/node` exists before `toolchain link`
103104
- JSON parsing issues in automation:
104105
- use `--output json` and keep `RUST_LOG` unset (or `off`) to avoid log noise
106+
- Error troubleshooting:
107+
- follow the `Hint:` action in the error message first, then rerun with `RUST_LOG=nodeup=debug` when deeper diagnostics are needed
105108

106109
## Documentation Links
107110

crates/nodeup/src/commands/run_cmd.rs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ pub fn execute(
2828
app: &NodeupApp,
2929
) -> Result<i32> {
3030
if command.is_empty() {
31-
return Err(NodeupError::invalid_input(
32-
"nodeup run requires delegated command arguments",
31+
return Err(NodeupError::invalid_input_with_hint(
32+
"Missing delegated command arguments for `nodeup run`",
33+
"Use `nodeup run [--install] <runtime> <command> [args...]`.",
3334
));
3435
}
3536

@@ -42,11 +43,13 @@ pub fn execute(
4243
if install {
4344
app.installer.ensure_installed(version, &app.releases)?;
4445
} else {
45-
return Err(NodeupError::not_found(format!(
46-
"Runtime {} is not installed. Re-run with --install or run nodeup toolchain \
47-
install {}",
48-
version, runtime
49-
)));
46+
return Err(NodeupError::not_found_with_hint(
47+
format!("Runtime {version} is not installed"),
48+
format!(
49+
"Install it with `nodeup toolchain install {runtime}` or retry with \
50+
`nodeup run --install {runtime} ...`."
51+
),
52+
));
5053
}
5154
}
5255
}
@@ -59,11 +62,17 @@ pub fn execute(
5962

6063
let executable = resolved.executable_path(&app.store, delegated_command);
6164
if !executable.exists() {
62-
return Err(NodeupError::not_found(format!(
63-
"Command '{}' is not available in runtime {}",
64-
delegated_command,
65-
resolved.runtime_id()
66-
)));
65+
return Err(NodeupError::not_found_with_hint(
66+
format!(
67+
"Command '{delegated_command}' is not available in runtime {}",
68+
resolved.runtime_id()
69+
),
70+
format!(
71+
"Check available commands with `nodeup which --runtime {} {delegated_command}` or \
72+
pick a runtime that provides it.",
73+
resolved.runtime_id()
74+
),
75+
));
6776
}
6877

6978
info!(

0 commit comments

Comments
 (0)