fix(task): show available tasks when run target missing#9141
Conversation
There was a problem hiding this comment.
Code Review
This pull request improves the error messages when a task is not found by providing similar task suggestions and a list of available tasks, including specific enhancements for monorepo environments. A new end-to-end test ensures these suggestions are correctly displayed. The review feedback suggests optimizing the task retrieval logic to avoid redundant asynchronous calls when operating within a monorepo.
| async fn tasks_for_missing_task_error( | ||
| config: &Config, | ||
| name: &str, | ||
| ) -> Result<(Arc<BTreeMap<String, Task>>, bool)> { | ||
| let tasks = config.tasks().await?; | ||
|
|
||
| // In monorepos, users usually need `tasks ls --all` after a miss. Load that | ||
| // same view for the error so sibling package tasks can be suggested. | ||
| if (name.starts_with("//") || config.is_monorepo()) | ||
| && let Ok(all_tasks) = config | ||
| .tasks_with_context(Some(&TaskLoadContext::all())) | ||
| .await | ||
| && !all_tasks.is_empty() | ||
| { | ||
| return Ok((all_tasks, true)); | ||
| } | ||
|
|
||
| Ok((tasks, false)) | ||
| } |
There was a problem hiding this comment.
This function can be made more efficient by avoiding the unconditional call to config.tasks().await?. This call is redundant when in a monorepo context and all tasks are loaded. By restructuring the function, we can load tasks only when necessary, improving performance in monorepo scenarios and improving readability.
| async fn tasks_for_missing_task_error( | |
| config: &Config, | |
| name: &str, | |
| ) -> Result<(Arc<BTreeMap<String, Task>>, bool)> { | |
| let tasks = config.tasks().await?; | |
| // In monorepos, users usually need `tasks ls --all` after a miss. Load that | |
| // same view for the error so sibling package tasks can be suggested. | |
| if (name.starts_with("//") || config.is_monorepo()) | |
| && let Ok(all_tasks) = config | |
| .tasks_with_context(Some(&TaskLoadContext::all())) | |
| .await | |
| && !all_tasks.is_empty() | |
| { | |
| return Ok((all_tasks, true)); | |
| } | |
| Ok((tasks, false)) | |
| } | |
| async fn tasks_for_missing_task_error( | |
| config: &Config, | |
| name: &str, | |
| ) -> Result<(Arc<BTreeMap<String, Task>>, bool)> { | |
| // In monorepos, users usually need tasks ls --all after a miss. Load that | |
| // same view for the error so sibling package tasks can be suggested. | |
| if name.starts_with("//") || config.is_monorepo() { | |
| if let Ok(all_tasks) = config | |
| .tasks_with_context(Some(&TaskLoadContext::all())) | |
| .await | |
| { | |
| if !all_tasks.is_empty() { | |
| return Ok((all_tasks, true)); | |
| } | |
| } | |
| } | |
| let tasks = config.tasks().await?; | |
| Ok((tasks, false)) | |
| } |
Greptile SummaryThis PR improves the error experience when Confidence Score: 5/5Safe to merge — all changes are on the error path and cannot affect successful task execution. No P0 or P1 findings. The logic is correct: tasks are loaded at most once per error path, the monorepo branch silently swallows its own errors before falling back, and the available-tasks table is capped. The new e2e test covers the key scenarios. All remaining observations are P2 or lower. No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["mise run <task>"] --> B["get_task_lists()"]
B --> C{"Task found?"}
C -- Yes --> D["Execute task"]
C -- No --> E["err_no_task(config, name)"]
E --> F["suggest_similar_commands(name)"]
E --> G["tasks_for_missing_task_error(config, name)"]
G --> H{"name starts with // OR config.is_monorepo()?"}
H -- Yes --> I["tasks_with_context(all)"]
I --> J{"non-empty?"}
J -- Yes --> K["return (all_tasks, showing_all=true)"]
J -- No --> L["config.tasks()"]
H -- No --> L
L --> M["return (tasks, showing_all=false)"]
K --> N{"tasks_for_error empty?"}
M --> N
N -- Yes --> O["bail: no tasks defined / untrusted config / non-exec files"]
N -- No --> P["similar_tasks(name, tasks_for_error)"]
P --> Q{"similar found?"}
Q -- Yes --> R["append 'Did you mean one of these?'"]
Q -- No --> S["skip suggestions"]
R --> T["append_available_tasks(err_msg, tasks_for_error, showing_all)"]
S --> T
T --> U["bail with formatted error message"]
Reviews (2): Last reviewed commit: "fix(task): avoid redundant missing-task ..." | Re-trigger Greptile |
a88fbd2 to
ebd880f
Compare
Hyperfine Performance
|
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.4.14 x -- echo |
22.8 ± 0.6 | 21.5 | 24.9 | 1.00 |
mise x -- echo |
23.6 ± 0.7 | 22.0 | 30.5 | 1.04 ± 0.04 |
mise env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.4.14 env |
22.5 ± 0.8 | 21.2 | 27.8 | 1.00 |
mise env |
22.9 ± 0.8 | 21.5 | 26.5 | 1.02 ± 0.05 |
mise hook-env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.4.14 hook-env |
23.4 ± 0.7 | 21.9 | 26.7 | 1.00 |
mise hook-env |
23.9 ± 0.8 | 22.3 | 26.8 | 1.02 ± 0.05 |
mise ls
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.4.14 ls |
20.4 ± 0.6 | 19.1 | 22.4 | 1.00 |
mise ls |
21.4 ± 0.8 | 19.6 | 23.8 | 1.05 ± 0.05 |
xtasks/test/perf
| Command | mise-2026.4.14 | mise | Variance |
|---|---|---|---|
| install (cached) | 150ms | 150ms | +0% |
| ls (cached) | 79ms | 81ms | -2% |
| bin-paths (cached) | 86ms | 86ms | +0% |
| task-ls (cached) | 832ms | 808ms | +2% |
### 🚀 Features - **(registry)** add .perl-version support for perl by @ergofriend in [#9102](#9102) - **(task)** add Tera template support for inline table run tasks by @iamkroot in [#9079](#9079) ### 🐛 Bug Fixes - **(env)** use runtime symlink paths for fuzzy versions by @jdx in [#9143](#9143) - **(github)** use full token resolution chain for attestation verification by @jdx in [#9154](#9154) - **(go)** Remove install-time version override for subpath packages by @c22 in [#9135](#9135) - **(npm)** respect install_before when resolving dist-tag versions by @webkaz in [#9145](#9145) - **(self-update)** ensure subcommand exists by @salim-b in [#9144](#9144) - **(task)** show available tasks when run target missing by @jdx in [#9141](#9141) - **(task)** forward task help args and add raw_args by @jdx in [#9118](#9118) - **(task)** remove red/yellow from task prefix colors by @lechuckcaptain in [#8782](#8782) - **(task)** merge TOML task block into same-named file task and surface resolved dir by @jdx in [#9147](#9147) - **(toolset)** round-trip serialized tool options by @atharvasingh7007 in [#9124](#9124) - **(vfox)** fallback to absolute bin path if env_keys not set by @80avin in [#9151](#9151) ### 📚 Documentation - make agent guide wording generic by @jdx in [#9142](#9142) ### 📦️ Dependency Updates - update ghcr.io/jdx/mise:deb docker digest to e019cb9 by @renovate[bot] in [#9160](#9160) - update ghcr.io/jdx/mise:copr docker digest to 8d25608 by @renovate[bot] in [#9159](#9159) - update ghcr.io/jdx/mise:rpm docker digest to 22e52da by @renovate[bot] in [#9161](#9161) - update ghcr.io/jdx/mise:alpine docker digest to a3da97c by @renovate[bot] in [#9158](#9158) - update rust docker digest to 4a2ef38 by @renovate[bot] in [#9162](#9162) - update ubuntu:24.04 docker digest to c4a8d55 by @renovate[bot] in [#9164](#9164) - update rust crate aws-lc-rs to v1.16.3 by @renovate[bot] in [#9165](#9165) - update ubuntu docker tag to resolute-20260413 by @renovate[bot] in [#9169](#9169) - update rust crate clap to v4.6.1 by @renovate[bot] in [#9166](#9166) - update taiki-e/install-action digest to a2352fc by @renovate[bot] in [#9163](#9163) - update rust crate ctor to 0.10 by @renovate[bot] in [#9170](#9170) - update rust crate tokio to v1.52.1 by @renovate[bot] in [#9167](#9167) - update rust crate rmcp-macros to 0.17 by @renovate[bot] in [#9173](#9173) - update rust crate signal-hook to 0.4 by @renovate[bot] in [#9177](#9177) - update rust crate zipsign-api to 0.2 by @renovate[bot] in [#9180](#9180) - update rust crate toml_edit to 0.25 by @renovate[bot] in [#9179](#9179) - update rust crate strum to 0.28 by @renovate[bot] in [#9178](#9178) ### 📦 Registry - add ibmcloud by @dnwe in [#9139](#9139) - add rush by @jdx in [#9146](#9146) ### New Contributors - @80avin made their first contribution in [#9151](#9151) - @atharvasingh7007 made their first contribution in [#9124](#9124) - @lechuckcaptain made their first contribution in [#8782](#8782) - @ergofriend made their first contribution in [#9102](#9102) - @dnwe made their first contribution in [#9139](#9139) ## 📦 Aqua Registry Updates #### New Packages (3) - [`controlplaneio-fluxcd/flux-operator`](https://github.com/controlplaneio-fluxcd/flux-operator) - [`dependency-check/DependencyCheck`](https://github.com/dependency-check/DependencyCheck) - [`kiro.dev/kiro-cli`](https://github.com/kiro.dev/kiro-cli) #### Updated Packages (2) - [`jreleaser/jreleaser/standalone`](https://github.com/jreleaser/jreleaser/standalone) - [`sigstore/cosign`](https://github.com/sigstore/cosign)
Summary
mise run <task>targets using the resolved task settasks ls --alltask view for monorepo missing-task errors so sibling package tasks are visibleValidation
mise run formatmise run test:e2e e2e/tasks/test_task_missing_suggestionsNote
Low Risk
Changes are limited to the missing-task error path and an added e2e test; primary risk is minor UX/performance impact from loading monorepo-wide tasks when a task is missing.
Overview
Improves the
mise run <task>missing-target error to suggest similar task names and append a compact Available tasks table (name + first-line description, capped at 20 with a hint to list all).For monorepo contexts (or
//task paths), the error now loads thetasks ls --allview so suggestions and the available-task list include sibling package tasks, and adds an e2e test covering both single-project and monorepo missing-task output.Reviewed by Cursor Bugbot for commit ebd880f. Bugbot is set up for automated code reviews on this repo. Configure here.