{"record":{"id":"fcb1c19cef04657d","repo":"jdx/mise","slug":"expected-run-to-be-a-string-or-array-of-strings","errorCode":null,"errorMessage":"expected `run` to be a string or array of strings","messagePattern":"expected `run` to be a string or array of strings","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/hooks.rs","lineNumber":95,"sourceCode":"    ) -> Result<Vec<Self>> {\n        let Some(phase) = BootstrapHookPhase::parse(phase_raw) else {\n            let valid = BootstrapHookPhase::iter()\n                .map(|phase| phase.as_str())\n                .collect::<Vec<_>>();\n            bail!(\n                \"unknown bootstrap hook phase {phase_raw:?}; valid phases are: {}\",\n                valid.join(\", \")\n            );\n        };\n        let runs = match value {\n            toml::Value::String(run) => vec![run],\n            toml::Value::Array(values) => string_array(values, \"expected string commands\")?,\n            toml::Value::Table(mut table) => match table.remove(\"run\") {\n                Some(toml::Value::String(run)) => vec![run],\n                Some(toml::Value::Array(values)) => {\n                    string_array(values, \"expected `run` to contain string commands\")?\n                }\n                Some(_) => bail!(\"expected `run` to be a string or array of strings\"),\n                None => bail!(\"expected a `run` command\"),\n            },\n            _ => bail!(\"expected a string, array of strings, or table with `run`\"),\n        };\n        let hooks = runs\n            .into_iter()\n            .filter_map(|run| {\n                let run = run.trim().to_string();\n                if run.is_empty() {\n                    warn!(\"[bootstrap.hooks.{phase}]: empty command, ignoring entry\");\n                    None\n                } else {\n                    Some(Self {\n                        phase,\n                        run,\n                        config_path: config_path.clone(),\n                    })\n                }","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/hooks.rs#L77-L113","documentation":"A hook table's `run` field must be either a TOML string or an array of strings. When `run` exists but is some other TOML type (integer, boolean, nested table, array of non-strings), from_toml bails with this message.","triggerScenarios":"Writing `run = 42`, `run = true`, `run = { cmd = \"x\" }`, or `run = [1, 2]` inside a hook table parsed by from_toml.","commonSituations":"Quoting mistakes in TOML; copying YAML/JSON-style config; trying to pass structured command options in `run` instead of a plain string or string list.","solutions":["Change `run` to a single string: run = \"echo hi\".","Or to an array of strings: run = [\"echo one\", \"echo two\"].","Ensure array elements are all quoted strings, not numbers or booleans."],"exampleFix":"// before\n[[hooks]]\nphase = \"pretool\"\nrun = { cmd = \"echo hi\", shell = \"bash\" }\n// after\n[[hooks]]\nphase = \"pretool\"\nrun = \"echo hi\"","handlingStrategy":"type-guard","validationCode":"fn valid_run(v: &toml::Value) -> bool {\n  match v { toml::Value::String(_) => true, toml::Value::Array(a) => a.iter().all(|x| x.is_str()), _ => false }\n}","typeGuard":"fn as_string_or_strings(v: &toml::Value) -> Option<Vec<String>> {\n  match v {\n    toml::Value::String(s) => Some(vec![s.clone()]),\n    toml::Value::Array(a) => a.iter().map(|x| x.as_str().map(str::to_string)).collect(),\n    _ => None,\n  }\n}","tryCatchPattern":"match load_hooks(config) {\n  Err(e) if e.to_string().contains(\"`run` to be a string\") => eprintln!(\"fix hook run field: {}\", e),\n  other => other?,\n}","preventionTips":["Always quote run commands as TOML strings.","Use arrays of quoted strings for multiple commands.","Validate mise.toml against the published JSON schema."],"tags":["config","toml","type-mismatch","hooks"],"backgroundTag":"config-type-mismatch","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}