{"record":{"id":"1ac7eab4c12de95e","repo":"jdx/mise","slug":"an-exec-entry-with-no-command","errorCode":null,"errorMessage":"an exec entry with no command","messagePattern":"an exec entry with no command","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/packslip.rs","lineNumber":1054,"sourceCode":"        .list_current_installed_versions(config)\n        .into_iter()\n        .find(|(b, _)| b.ba().short == name || b.tool_name() == name || b.id() == name);\n    match by_name {\n        Some(found) => Ok(found),\n        None => bail!(\"{name} is not an active, installed tool or one of their executables\"),\n    }\n}\n\n/// Run one of the tool's own executables and return what it printed.\nasync fn run_tool(\n    config: &Arc<Config>,\n    backend: &Arc<dyn Backend>,\n    tv: &ToolVersion,\n    argv: &[String],\n    env: &BTreeMap<String, String>,\n) -> Result<String> {\n    let Some((program, args)) = argv.split_first() else {\n        bail!(\"an exec entry with no command\");\n    };\n    let Some(path) = backend.which(config, tv, program).await? else {\n        bail!(\"{} has no executable called {program}\", tv.style());\n    };\n    run_resource_command(\n        &path,\n        args,\n        env,\n        &tv.install_path(),\n        std::time::Duration::from_secs(5),\n    )\n    .await\n}\n\n/// Run vendor resource generation outside the user's project, without\n/// input, under a deadline. Empty output is a failed source, never a cache hit.\nasync fn run_resource_command(\n    path: &Path,","sourceCodeStart":1036,"sourceCodeEnd":1072,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/packslip.rs#L1036-L1072","documentation":"run_tool executes one of a tool's own executables as described by an argv list from the packslip resource commands. Before running, it takes the first element as the program via argv.split_first(); an empty argv has no command at all, so it bails. This is a malformed-manifest guard: an exec entry must name the command to run.","triggerScenarios":"A resource command's exec argv array is empty (e.g. `exec = []` or a computed/templated argv that expands to nothing), so split_first() returns None when run_tool is invoked from completion_script.","commonSituations":"A hand-edited or templated packslip manifest where the command string was left blank or a template variable failed to expand; array built programmatically from an empty config value.","solutions":["Fix the manifest/resource command so the exec entry's argv array has at least one element (the program).","If the argv comes from a template, verify the variable that supplies the command resolves to a non-empty value.","Validate the packslip resource commands before running (run the packslip check/validation flow)."],"exampleFix":"# before (packslip manifest)\nexec = []\n\n# after\nexec = [\"rg\", \"--version\"]","handlingStrategy":"validation","validationCode":"if argv.is_empty() {\n    return Err(anyhow!(\"resource command argv must contain at least a program\"));\n}","typeGuard":"let Some((program, args)) = argv.split_first() else { return Err(anyhow!(\"an exec entry with no command\")); };","tryCatchPattern":"match run_tool(config, &backend, &tv, &argv, &env).await {\n    Err(e) if e.to_string().contains(\"no command\") => eprintln!(\"Fix the exec entry: it must name a program\"),\n    Ok(out) => use(out),\n    Err(e) => return Err(e),\n}","preventionTips":["Never emit an empty argv array in packslip exec entries.","Validate manifests (check that every exec entry has a non-empty command) before execution.","Test templated commands resolve to non-empty strings in CI."],"tags":["packslip","manifest","argv","validation"],"backgroundTag":"missing-required-argument","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}