jdx/mise · error

an exec entry with no command

Error message

an exec entry with no command

What it means

run_tool executes an entry from the tool's own exec/completion config. The argv is expected to have at least a program; when the entry is an empty array (or has no elements), split_first returns None and this error is raised.

Solutions

  1. Provide a command in the exec entry, e.g. exec = ["tool", "--help"] or ["tool", "completions"]
  2. Check templated values so the command does not expand to empty
  3. Fix the packslip entry so argv has at least one element

Example fix

// before (packslip)
// exec = []
// after
// exec = ["mytool", "completions"]
Defensive patterns

Strategy: validation

Validate before calling

if (!Array.isArray(exec) || exec.length === 0) throw new Error('exec entry needs at least a command');

Type guard

const hasCommand = (argv: unknown): argv is [string, ...string[]] => Array.isArray(argv) && argv.length > 0 && typeof argv[0] === 'string';

Try / catch

try { await runTool(...) } catch (e) { if (/an exec entry with no command/.test(e.message)) { fixPackslipExec(); } else { throw e; } }

Prevention

When it happens

Trigger: A packslip's exec/completion resource entry is an empty list, e.g. exec = [] or a command field that resolves to nothing after parsing.

Common situations: Hand-written packslip with an empty exec array, templating/substitution that evaluated to nothing, an optional command field left blank.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/1ac7eab4c12de95e. Report an issue: GitHub.

Appendix: source

Thrown at src/packslip.rs:1358

        .list_current_installed_versions(config)
        .into_iter()
        .find(|(b, _)| b.ba().short == name || b.tool_name() == name || b.id() == name);
    match by_name {
        Some(found) => Ok(found),
        None => bail!("{name} is not an active, installed tool or one of their executables"),
    }
}

/// Run one of the tool's own executables and return what it printed.
async fn run_tool(
    config: &Arc<Config>,
    backend: &Arc<dyn Backend>,
    tv: &ToolVersion,
    argv: &[String],
    env: &BTreeMap<String, String>,
) -> Result<String> {
    let Some((program, args)) = argv.split_first() else {
        bail!("an exec entry with no command");
    };
    let Some(path) = backend.which(config, tv, program).await? else {
        bail!("{} has no executable called {program}", tv.style());
    };
    run_resource_command(
        &path,
        args,
        env,
        &tv.install_path(),
        std::time::Duration::from_secs(5),
    )
    .await
}

/// Run vendor resource generation outside the user's project, without
/// input, under a deadline. Empty output is a failed source, never a cache hit.
async fn run_resource_command(
    path: &Path,

View on GitHub (pinned to 533346cc37)