{"record":{"id":"43e3fb3c059a1993","repo":"jdx/mise","slug":"unknown-bootstrap-hook-phase-phase-raw-valid","errorCode":null,"errorMessage":"unknown bootstrap hook phase {phase_raw:?}; valid phases are: {}","messagePattern":"unknown bootstrap hook phase (.+?); valid phases are: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/hooks.rs","lineNumber":76,"sourceCode":"impl fmt::Display for BootstrapHookPhase {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.write_str(self.as_str())\n    }\n}\n\n#[derive(Debug, Clone, PartialEq, Eq)]\npub struct BootstrapHook {\n    pub phase: BootstrapHookPhase,\n    pub run: String,\n}\n\nimpl BootstrapHook {\n    pub fn from_toml(phase_raw: &str, value: toml::Value) -> 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","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/hooks.rs#L58-L94","documentation":"BootstrapHook::from_toml treats every key under [bootstrap.hooks] as a phase name. Valid phases are pre-packages, post-packages, pre-repos, post-repos, pre-dotfiles, post-dotfiles, pre-defaults, post-defaults, pre-user, post-user, pre-tools, post-tools, and final (parse() normalizes '_' to '-', so pre_packages is also accepted). Any other key bails with this error and the message lists the accepted phases.","triggerScenarios":"Writing an unknown key under [bootstrap.hooks], e.g. [bootstrap.hooks.pre_package] (singular), [bootstrap.hooks.post-install], or [bootstrap.hooks.before-tools], while mise parses config during bootstrap.","commonSituations":"Guessing phase names from other tools' hook systems (pre-commit, Husky) instead of checking the list; typos and singular/plural mistakes; configs written against docs that renamed phases.","solutions":["Rename the key to one of the phases enumerated in the error message (pre-packages, post-packages, pre-repos, post-repos, pre-dotfiles, post-dotfiles, pre-defaults, post-defaults, pre-user, post-user, pre-tools, post-tools, final)","Check for singular/plural mistakes (it is pre-packages, not pre-package)","Re-run mise bootstrap to confirm the hooks table parses"],"exampleFix":"# before\n[bootstrap.hooks]\npost-install = \"./setup.sh\"\n\n# after\n[bootstrap.hooks]\npost-tools = \"./setup.sh\"","handlingStrategy":"validation","validationCode":"# verify every phase key is known before bootstrap\nfor p in $(git config -f mise.toml --get-regexp '^bootstrap\\.hooks\\.' 2>/dev/null | cut -d. -f3- | cut -d' ' -f1); do\n  case \"$p\" in pre-packages|post-packages|pre-repos|post-repos|pre-dotfiles|post-dotfiles|pre-defaults|post-defaults|pre-user|post-user|pre-tools|post-tools|final) ;; *) echo \"unknown hook phase: $p\";; esac\ndone","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Copy phase names from the error message or docs, not from other tools' hook systems","Run mise bootstrap right after adding hooks to catch typos early","Prefer dash-form names (pre-packages); underscores work but dashes match the docs"],"tags":["mise","bootstrap","hooks","toml","config-validation"],"backgroundTag":"unknown-config-key","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}