jdx/mise · error
expected value of to be a , got
Error message
expected value of {} to be a {}, got: {} What it means
This is the `parse_error!` macro from src/toml.rs, used when a value in a mise.toml-style config file fails a type assertion (e.g. a string found where a table/array was expected). It renders a colored error naming the key, the expected type, and the offending value, then bails via eyre. It exists to give users a consistent, friendly message for malformed config values.
Solutions
- Fix the value in the config file to match the expected type shown in the message (e.g. change `tools = "node@20"` to `[tools]\nnode = "20"`).
- Check the docs for the specific key's expected shape (table, array, bool, etc.).
- Validate the TOML file with a schema validator or `mise` config check if available.
- Pin down whether another mise.toml in the hierarchy (system/global/project) contains the bad value.
Example fix
// before [env] NODE_ENV = "production" # but written as: env = "NODE_ENV=production" // after [env] NODE_ENV = "production"
Defensive patterns
Strategy: validation
Validate before calling
if let Some(tbl) = value.as_table() { /* proceed */ } else { eprintln!("key '{}' must be a table, got: {:?}", key, value); return; } Type guard
fn as_table<'a>(v: &'a toml::Value, key: &str) -> Option<&'a toml::value::Table> { v.as_table().filter(|_| true).or_else(|| { eprintln!("config key '{}' must be a table", key); None }) } Try / catch
match parse_config() { Err(e) if e.to_string().contains("expected value of") => { /* fall back to defaults, log which key */ }, Err(e) => return Err(e), Ok(c) => c } Prevention
- Use a TOML schema validator in CI against your mise.toml.
- Keep tables under their own [section] headers rather than inline strings.
- Test config changes with `mise run` before committing them.
When it happens
Trigger: Any call site that invokes `parse_error!(key, val, expected_type)` after a type-check on a deserialized TOML value fails — e.g. `let Some(t) = v.as_table() else { parse_error!(key, v, "table") }`.
Common situations: Hand-editing mise.toml and writing a string where a table is needed (e.g. `[tools]` vs `tools = "node"`), copy-pasting config between tools, or a schema change in a newer mise version making an old value shape invalid.
Related errors
- additional_artifacts must be an array in lockfile
- backend must be a string or table
- expected `run` to be a string or array of strings
- [history] exclude in
- [history] in is not a table
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/15c3fd1dd7425dc5.
Report an issue: GitHub.
Appendix: source
Thrown at src/toml.rs:8
use std::collections::HashSet;
#[macro_export]
macro_rules! parse_error {
($key:expr, $val:expr, $t:expr) => {{
use eyre::bail;
bail!(
r#"expected value of {} to be a {}, got: {}"#,
$crate::ui::style::eyellow($key),
$crate::ui::style::ecyan($t),
$crate::ui::style::eblue($val.to_string().trim()),
)
}};
}
pub(crate) fn dedup_toml_array(array: &toml_edit::Array) -> toml_edit::Array {
let mut seen = HashSet::new();
let mut deduped = toml_edit::Array::new();
for item in array.iter() {
if seen.insert(item.as_str()) {
deduped.push(item.clone());
}
}
deduped
}View on GitHub (pinned to 533346cc37)