{"record":{"id":"9b9f8caf6c4e75ed","repo":"jdx/mise","slug":"default-inline-shell-args-must-not-be-empty","errorCode":null,"errorMessage":"default inline shell args must not be empty","messagePattern":"default inline shell args must not be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/hooks.rs","lineNumber":133,"sourceCode":"            _ => bail!(\"{message}\"),\n        }\n    }\n    Ok(out)\n}\n\npub async fn run_phase(\n    hooks: &[BootstrapHook],\n    phase: BootstrapHookPhase,\n    dry_run: bool,\n) -> Result<()> {\n    let phase_hooks: Vec<_> = hooks.iter().filter(|hook| hook.phase == phase).collect();\n    if phase_hooks.is_empty() {\n        return Ok(());\n    }\n    info!(\"bootstrap: {phase} hooks\");\n    let shell = Settings::get().default_inline_shell()?;\n    let Some((program, shell_args)) = shell.split_first() else {\n        bail!(\"default inline shell args must not be empty\");\n    };\n    for hook in phase_hooks {\n        if dry_run {\n            miseprintln!(\"{} {}\", shell.join(\" \"), shell_words::quote(&hook.run));\n            continue;\n        }\n        info!(\"$ {}\", hook.run);\n        crate::cmd::CmdLineRunner::new(program)\n            .cmd_body_args(shell_args, &hook.run)\n            .raw(true)\n            .execute_async()\n            .await?;\n    }\n    Ok(())\n}\n\n#[cfg(test)]\nmod tests {","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/hooks.rs#L115-L151","documentation":"run_phase executes each hook through the settings-derived inline shell (Settings::default_inline_shell(), built from the unix_default_inline_shell_args / windows_default_inline_shell_args settings). If that setting resolves to an empty list, split_first() returns None and mise bails with this message before running any hook. It only fires when at least one hook is registered for the phase being reached.","triggerScenarios":"Setting unix_default_inline_shell_args = \"\" (or windows_default_inline_shell_args = \"\" on Windows) in mise settings while [bootstrap.hooks] defines at least one command, then running mise bootstrap to a phase with hooks.","commonSituations":"Hardening profiles that override the inline shell and accidentally blank it; hand-edited settings.toml entries that shell-word-split to zero tokens; environment-specific settings files overriding the shell.","solutions":["Check the active value: `mise settings get unix_default_inline_shell_args` (or windows_default_inline_shell_args) and set a real shell, e.g. `mise settings set unix_default_inline_shell_args \"sh -c\"`","Remove the empty override so the built-in default applies","Re-run mise bootstrap and confirm the phase hooks execute"],"exampleFix":"# before (settings)\nunix_default_inline_shell_args = \"\"\n\n# after\nunix_default_inline_shell_args = \"sh -c\"","handlingStrategy":"validation","validationCode":"# confirm the inline shell resolves to a non-empty program before bootstrap\nmise settings get unix_default_inline_shell_args 2>/dev/null || true\n# on macOS/Linux it must print something like: sh -c","typeGuard":null,"tryCatchPattern":null,"preventionTips":["After overriding unix_default_inline_shell_args / windows_default_inline_shell_args, verify with mise settings get that it is non-empty","Never set these settings to a blank string; remove the override instead","Add a settings smoke-check to provisioning scripts before running bootstrap hooks"],"tags":["mise","bootstrap","hooks","shell","settings"],"backgroundTag":"invalid-setting-value","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}