{"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":502,"sourceCode":"                .map(|options| {\n                    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                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":484,"sourceCodeEnd":520,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/registry.rs#L484-L520","documentation":"In parse_registry_backend, each element of a registry entry's backends array must be either a plain string (shorthand like \"aqua:owner/repo\") or a TOML table with full/platforms/options fields. Any other TOML type — integer, float, boolean, array, or datetime — falls through to this bail and the registry fails to load.","triggerScenarios":"Writing backends = [123], backends = [true], backends = [[\"aqua:owner/repo\"]], or backends = [1979-05-27] in a registry/*.toml entry. Also triggered by YAML-to-TOML conversions that turn a single backend string into a nested array.","commonSituations":"Contributing a registry entry and wrapping the backend in extra brackets; automated tooling that emits a non-string scalar; merging registry entries by hand and leaving a stray value.","solutions":["Use the string form for simple cases: backends = [\"aqua:cli/cli\"].","Use the table form only when you need full/platforms/options: backends = [{ full = \"aqua:cli/cli\", platforms = [\"linux\", \"macos\"] }].","Ensure the backends array itself is non-empty — an empty array is rejected separately just above this code.","Validate with the registry test suite (`cargo test registry`) before submitting."],"exampleFix":"# before\nbackends = [[\"aqua:cli/cli\"]]\n# after\nbackends = [\"aqua:cli/cli\"]","handlingStrategy":"validation","validationCode":"# every backends[] element must be a string or a table\npython3 - <<'EOF'\nimport sys, tomllib\ncfg = tomllib.load(open('registry/mytool.toml','rb'))\nfor b in cfg['tools']['mytool']['backends']:\n    if not isinstance(b, (str, dict)):\n        sys.exit(f'backend must be a string or table, got: {b!r}')\nEOF","typeGuard":"def is_registry_backend(v) -> bool: return isinstance(v, (str, dict))","tryCatchPattern":null,"preventionTips":["Prefer the one-line string form: backends = [\"aqua:owner/repo\"].","Never wrap backends entries in extra brackets.","Lint TOML with a schema-aware tool before contributing."],"tags":["mise","registry","toml","type-mismatch","backends"],"backgroundTag":"config-type-mismatch","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}