{"record":{"id":"15c3fd1dd7425dc5","repo":"jdx/mise","slug":"expected-value-of-to-be-a-got","errorCode":null,"errorMessage":"expected value of {} to be a {}, got: {}","messagePattern":"expected value of (.+?) to be a (.+?), got: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/toml.rs","lineNumber":8,"sourceCode":"use std::collections::HashSet;\n\n#[macro_export]\nmacro_rules! parse_error {\n    ($key:expr, $val:expr, $t:expr) => {{\n        use eyre::bail;\n\n        bail!(\n            r#\"expected value of {} to be a {}, got: {}\"#,\n            $crate::ui::style::eyellow($key),\n            $crate::ui::style::ecyan($t),\n            $crate::ui::style::eblue($val.to_string().trim()),\n        )\n    }};\n}\n\npub(crate) fn dedup_toml_array(array: &toml_edit::Array) -> toml_edit::Array {\n    let mut seen = HashSet::new();\n    let mut deduped = toml_edit::Array::new();\n    for item in array.iter() {\n        if seen.insert(item.as_str()) {\n            deduped.push(item.clone());\n        }\n    }\n    deduped\n}","sourceCodeStart":1,"sourceCodeEnd":26,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/toml.rs#L1-L26","documentation":"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.","triggerScenarios":"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\") }`.","commonSituations":"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.","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."],"exampleFix":"// before\n[env]\nNODE_ENV = \"production\"\n# but written as:\nenv = \"NODE_ENV=production\"\n// after\n[env]\nNODE_ENV = \"production\"","handlingStrategy":"validation","validationCode":"if let Some(tbl) = value.as_table() { /* proceed */ } else { eprintln!(\"key '{}' must be a table, got: {:?}\", key, value); return; }","typeGuard":"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 }) }","tryCatchPattern":"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 }","preventionTips":["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."],"tags":["config","toml","type-mismatch","parsing"],"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"}