jdx/mise · error
must be a string or array of strings
Error message
{key} must be a string or array of strings What it means
The pipx backend's string_list helper parses backend options such as `with` and `expose`, which must each be a single string or an array of strings. If the TOML option is another type (integer, boolean, table) or an array containing non-strings, mise raises this error naming the offending key.
Solutions
- Quote string values: `with = "pytest"`
- Ensure arrays contain only quoted strings: `expose = ["black", "ruff"]`
- Remove the malformed option if it is not needed
- Run `mise settings` / docs to confirm the option's expected type
Example fix
# before
[tools]
ruff = { source = "pipx", with = [1, 2] }
# after
[tools]
ruff = { source = "pipx", with = ["black"] } Defensive patterns
Strategy: validation
Validate before calling
# Validate tool config values are strings or arrays of strings jq -e '.tools | to_entries | map(.value | (type == "string" or ((type == "object") and ((.with // []) | type == "array")))) | all' mise.toml 2>/dev/null || cat mise.toml
Type guard
const isStringList = (v: unknown): v is string | string[] => typeof v === 'string' || (Array.isArray(v) && v.every(x => typeof x === 'string'));
Prevention
- Always quote string values in mise.toml backend options
- Keep arrays homogeneous (all strings)
- Validate mise.toml against the mise schema (mise run render:schema / JSON schema in editors)
When it happens
Trigger: A `[tools]` entry like `foo = { source = "pipx", with = 123 }` or `expose = [true, "pkg"]` — string_list receives a TOML value that is neither a string nor an array of strings.
Common situations: Unquoted numeric or boolean values in mise.toml; a table passed where a list is expected; copy-paste from docs with wrong syntax; tool-versions/lockfile opts carrying non-string values.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- dependency_prereleases must be a string
- expose must contain named Python package requirements
- cannot contain empty values
- pipx is required to install
- rust's mr_boxington option requires mr-boxington in…
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/e9b0e322223fadfb.
Report an issue: GitHub.
Appendix: source
Thrown at src/backend/pipx.rs:90
let values = match value {
toml::Value::String(value) => {
if value.trim_start().starts_with('[') {
serde_json::from_str(value)
.map_err(|_| eyre!("{key} must be a string or array of strings"))?
} else {
vec![value.clone()]
}
}
toml::Value::Array(values) => values
.iter()
.map(|value| {
value
.as_str()
.map(str::to_owned)
.ok_or_else(|| eyre!("{key} must be a string or array of strings"))
})
.collect::<Result<Vec<_>>>()?,
_ => bail!("{key} must be a string or array of strings"),
};
if values.iter().any(|value| value.trim().is_empty()) {
bail!("{key} cannot contain empty values");
}
Ok(values)
}
fn with(&self) -> Result<Vec<String>> {
self.string_list("with")
}
fn expose(&self) -> Result<Vec<String>> {
self.string_list("expose")
}
fn exposed_package_names(&self) -> Result<Vec<String>> {
self.expose()?
.into_iter()View on GitHub (pinned to 533346cc37)