{"record":{"id":"a93174165402deaf","repo":"jdx/mise","slug":"expected-a-run-command","errorCode":null,"errorMessage":"expected a `run` command","messagePattern":"expected a `run` command","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/hooks.rs","lineNumber":96,"sourceCode":"        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                }\n            })","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/hooks.rs#L78-L114","documentation":"Bootstrap hook TOML parsing reached the command specification but found no `run` key: a hook entry must declare what to execute (a run command, string array, or table with run), and this table has none of those, so from_toml rejects it.","triggerScenarios":"Writing a hook table with only phase (and maybe other metadata) but no `run`, e.g. `[[hooks]] phase = \"pretool\"` with no run key.","commonSituations":"Forgot to fill in the command after scaffolding the hook; deleted the run line during editing; renamed the key to something like `command` or `script` by mistake.","solutions":["Add a `run` string or array of strings to the hook table.","If the command lives under another key, rename that key to `run`.","Remove the empty hook table if it's not needed."],"exampleFix":"// before\n[[hooks]]\nphase = \"pretool\"\n// after\n[[hooks]]\nphase = \"pretool\"\nrun = \"mise run prepare\"","handlingStrategy":"validation","validationCode":"fn hook_has_run(table: &toml::value::Table) -> bool { table.contains_key(\"run\") }","typeGuard":null,"tryCatchPattern":"match load_hooks(config) {\n  Err(e) if e.to_string().contains(\"expected a `run` command\") => eprintln!(\"hook missing run: {}\", e),\n  other => other?,\n}","preventionTips":["Always pair `phase` with a `run` key when defining hooks.","Don't rename `run` to `command`/`script` — only `run` is accepted.","Validate hook tables against the mise schema in CI."],"tags":["config","toml","missing-field","hooks"],"backgroundTag":"missing-required-config-field","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"}