{"record":{"id":"6db639cfe029f835","repo":"jdx/mise","slug":"backend-must-be-a-string-or-table","errorCode":null,"errorMessage":"backend must be a string or table","messagePattern":"backend must be a string or table","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/registry.rs","lineNumber":585,"sourceCode":"                    options\n                        .iter()\n                        .map(|(key, value)| {\n                            let mut serialized = String::new();\n                            value.serialize(toml::ser::ValueSerializer::new(&mut serialized))?;\n                            Ok((leak_string(key.clone()), leak_string(serialized)))\n                        })\n                        .collect::<Result<Vec<_>>>()\n                })\n                .transpose()?\n                .unwrap_or_default();\n            Ok(RegistryBackend {\n                full: leak_string(full.to_string()),\n                platforms: leak_vec(platforms),\n                min_version,\n                options: leak_vec(options),\n            })\n        }\n        _ => bail!(\"backend must be a string or table\"),\n    }\n}\n\nfn parse_registry_test(value: &toml::Value) -> Result<RegistryToolTest> {\n    let table = value\n        .as_table()\n        .ok_or_else(|| eyre::eyre!(\"test must be a table\"))?;\n    let cmd = table\n        .get(\"cmd\")\n        .and_then(toml::Value::as_str)\n        .ok_or_else(|| eyre::eyre!(\"test.cmd must be a string\"))?;\n    let expected = table\n        .get(\"expected\")\n        .and_then(toml::Value::as_str)\n        .ok_or_else(|| eyre::eyre!(\"test.expected must be a string\"))?;\n    let tools = string_array(table.get(\"tools\"), \"test.tools\")?;\n    Ok(RegistryToolTest {\n        cmd: leak_string(cmd.to_string()),","sourceCodeStart":567,"sourceCodeEnd":603,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/registry.rs#L567-L603","documentation":"The registry TOML parser accepts a backend definition either as a plain string (shorthand) or as a table with fields like full/platforms/options. Any other TOML type (array, integer, boolean, etc.) falls into the `_` match arm and bails with this message.","triggerScenarios":"A registry entry's backend value written as a non-string, non-table type, e.g. `backend = [\"github\"]`, `backend = 1`, or `backend = true`, while `parse_backend` pattern-matches.","commonSituations":"Hand-editing registry/ TOML files and accidentally adding brackets around the backend name; tool-generated TOML emitting arrays for repeated keys; merging duplicate entries that TOML turns into an array.","solutions":["Write the backend as a plain string: `backend = \"github:user/repo\"`.","Or use the table form with fields like `backend = { full = \"...\", platforms = [...] }`.","Remove stray brackets/quotes around the value and re-run the failing command."],"exampleFix":"// before (registry TOML)\nbackend = [\"github:jdx/mise-node\"]\n// after\nbackend = \"github:jdx/mise-node\"","handlingStrategy":"validation","validationCode":"const b = table.get('backend');\nif (typeof b !== 'string' && !(b && typeof b === 'object' && !Array.isArray(b)))\n  throw new Error('backend must be a string or table');","typeGuard":"const isBackendValue = (v) => typeof v === 'string' || (v !== null && typeof v === 'object' && !Array.isArray(v));","tryCatchPattern":null,"preventionTips":["Write backend entries as `backend = \"provider:repo\"` strings, never arrays.","Run `mise registry` or a TOML linter after hand-editing registry files."],"tags":["registry","config","toml","type-mismatch"],"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"}