jdx/mise · error

plugin task name should be registered before spawning

Error message

plugin task name should be registered before spawning

What it means

mise runs plugin operations (install/update/uninstall across many plugins) concurrently in a tokio JoinSet, tracking a HashMap<Id, String> from spawned task id to plugin name. take_plugin_name removes and returns the name for a finished task and expects it to have been registered by spawn_plugin_task (src/cli/plugins/mod.rs:21-37). The expect fires if a completed task's id is missing from the map — bookkeeping between spawns and joined results diverged.

Source

Thrown at src/cli/plugins/mod.rs:24

use eyre::{Report, Result, WrapErr, eyre};
use tokio::task::{Id, JoinSet};

use crate::config::Config;

pub(crate) mod install;
mod link;
mod ls;
mod ls_remote;
mod uninstall;
mod update;

type PluginTaskResult = Result<()>;
type PluginTaskNames = HashMap<Id, String>;

fn take_plugin_name(task_names: &mut PluginTaskNames, id: Id) -> String {
    task_names
        .remove(&id)
        .expect("plugin task name should be registered before spawning")
}

fn spawn_plugin_task<F>(
    tasks: &mut JoinSet<PluginTaskResult>,
    task_names: &mut PluginTaskNames,
    plugin: impl Into<String>,
    task: F,
) where
    F: Future<Output = PluginTaskResult> + Send + 'static,
{
    let task = tasks.spawn(task);
    task_names.insert(task.id(), plugin.into());
}

async fn join_plugin_tasks(
    mut tasks: JoinSet<PluginTaskResult>,
    mut task_names: PluginTaskNames,
    operation: &'static str,

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. If hit as a user: update mise — internal concurrency bookkeeping bug; retry the plugin operation once after the panic since plugin state may be partially applied
  2. As a contributor: always spawn via spawn_plugin_task so the id is registered, and never consume JoinSet results outside join_plugin_tasks
  3. Add a regression test with a mix of panicking and succeeding tasks (see the existing tests in src/cli/plugins/mod.rs)
  4. Report at https://github.com/jdx/mise/issues with the panic backtrace

Example fix

// before: spawning directly, id never registered
tasks.spawn(install_plugin(plugin.clone()));
// later: take_plugin_name(&mut task_names, id) -> panic

// after: route through the helper
spawn_plugin_task(&mut tasks, &mut task_names, plugin.clone(), install_plugin(plugin));
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Only a code change that polls the JoinSet without going through spawn_plugin_task's registration, or that takes a name twice for the same id; current code registers on every spawn and consumes each joined id exactly once (success, error, and panic/JoinError paths all route through take_plugin_name). Users running `mise plugins update|install|uninstall` in a correctly built mise cannot trigger it.

Common situations: Contributors adding new parallel plugin flows that call tasks.join_next_with_id() directly or forget task_names insertion; broken builds. The module's own tests (panicked_plugin_task_does_not_cancel_other_tasks) pin the intended behavior.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22). Data as JSON: /api/errors/20ac484a10755f54. Report an issue: GitHub.