{"record":{"id":"888315e0086d5733","repo":"jdx/mise","slug":"deps-run-command-cannot-be-empty","errorCode":null,"errorMessage":"deps run command cannot be empty","messagePattern":"deps run command cannot be empty","errorType":"validation","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/deps/mod.rs","lineNumber":136,"sourceCode":"    pub env: BTreeMap<String, String>,\n    /// Working directory (defaults to project root)\n    pub cwd: Option<PathBuf>,\n    /// Human-readable description of what this command does\n    pub description: String,\n}\n\nimpl DepsCommand {\n    /// Create a DepsCommand from a run string like \"npm install\"\n    ///\n    /// Wraps the command with `sh -c` (matching task execution behavior)\n    /// so shell features like pipes, redirects, and `&&` work.\n    pub fn from_string(\n        run: &str,\n        project_root: &Path,\n        config: &rule::DepsProviderConfig,\n    ) -> Result<Self> {\n        if run.trim().is_empty() {\n            bail!(\"deps run command cannot be empty\");\n        }\n\n        let shell = Settings::get().default_inline_shell()?;\n        let (program, shell_args) = shell.split_first().ok_or_else(|| {\n            eyre::eyre!(\"default inline shell is empty; check unix_default_inline_shell_args / windows_default_inline_shell_args\")\n        })?;\n\n        let mut args: Vec<String> = shell_args.to_vec();\n        args.push(run.to_string());\n\n        Ok(Self {\n            program: program.to_string(),\n            args,\n            env: config.env.clone(),\n            cwd: config\n                .dir\n                .as_ref()\n                .map(|d| project_root.join(d))","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/deps/mod.rs#L118-L154","documentation":"`DepsCommand::from_string` (src/deps/mod.rs:124) wraps a provider's run string with the configured inline shell (`sh -c`-style) so pipes and `&&` work. An empty or whitespace-only command would spawn a shell that does nothing, so it is rejected up front with `run.trim().is_empty()`.","triggerScenarios":"A deps provider config whose run string is empty or only whitespace — `run = \"\"`, `run = \"   \"` — or a templated run string whose variables expand to nothing when the config is resolved.","commonSituations":"Scaffolded/placeholder provider blocks that were never filled in; `run = \"{{var}}\"` with `var` unset; TOML/YAML indentation mistakes putting the command under the wrong key; commented-out runs leaving an empty string behind.","solutions":["Set a real command in the provider's run field","If the run string is templated, verify every variable it references is defined and non-empty in that context","Delete the provider block entirely if it was scaffolded but unused"],"exampleFix":"# before\n[deps.providers.mytool]\nrun = \"\"\n\n# after\n[deps.providers.mytool]\nrun = \"mytool install\"","handlingStrategy":"validation","validationCode":"# reject empty run commands before mise loads them\nimport tomllib, sys\ncfg = tomllib.load(open(\"mise.toml\", \"rb\"))\nfor pid, p in cfg.get(\"deps\", {}).get(\"providers\", {}).items():\n    if not str(p.get(\"run\", \"\")).strip():\n        sys.exit(f\"provider {pid} has an empty run command\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never commit scaffolded provider blocks with placeholder empty runs — delete them until real","If run strings are templated, default the variable (e.g. `run = \"{{env.CMD|...}}\"`) or assert it is set","Lint deps config in CI alongside task config"],"tags":["mise","deps","config","validation"],"backgroundTag":"empty-config-value","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}