jdx/mise · error
invalid daemon name ; use letters, numbers, '.', '_' or
Error message
invalid daemon name {name:?}; use letters, numbers, '.', '_' or '-' What it means
Daemon declarations in `[daemons.<name>]` must have names made only of ASCII letters, digits, '_', '-', and '.', and must not start or end with '-'. The `load` function validates each daemon name and bails with this message for anything else. This keeps daemon names usable as identifiers/process labels.
Solutions
- Rename the daemon key to only use letters, numbers, '.', '_' or '-'.
- Remove leading/trailing hyphens from the key.
- If the name comes from templating or a variable, sanitize it before writing the config.
Example fix
# before (mise.toml) [daemons."my api"] run = "python server.py" # after [daemons.my_api] run = "python server.py"
Defensive patterns
Strategy: validation
Validate before calling
# shell: validate daemon names in mise.toml before running mise grep -E '^\[daemons\.[^]]+\]' mise.toml | grep -vE '^\[daemons\.[A-Za-z0-9_.-]+\]$' && echo "invalid daemon name"
Prevention
- Use snake_case or kebab-case daemon names without spaces or slashes.
- Avoid generating daemon keys from arbitrary service labels; sanitize first.
- Keep daemon table keys on one line and quoted only when necessary.
When it happens
Trigger: Declaring a daemon in mise.toml whose table key contains spaces, slashes, non-ASCII characters, or starts/ends with '-', parsed during config load (load is invoked by task/env expansion paths such as daemons_merge_before_expanding_tools_and_exports).
Common situations: Copy-pasting a service name like `my daemon` or `api/server` into a `[daemons.*]` key; trailing hyphens from templated names; quoting mistakes in TOML keys.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- [daemons. ] requires preset when specifying version or…
- [daemons. ] requires run or preset
- agent name ' ' must contain only letters, numbers, '.'…
- backend must be a string or table
- collection updates require scalar or array values
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/d3b1a779851ae90b.
Report an issue: GitHub.
Appendix: source
Thrown at src/daemons/mod.rs:82
cf.get_path().to_path_buf(),
cf.project_root().unwrap_or_else(|| cf.config_root()),
),
);
}
}
let mut set = DaemonSet::default();
for (name, (declaration, source, root)) in declarations {
if name.is_empty()
|| name == "."
|| name.contains("..")
|| name.contains("--")
|| name.starts_with('-')
|| name.ends_with('-')
|| !name
.chars()
.all(|c| c.is_ascii_alphanumeric() || matches!(c, '_' | '-' | '.'))
{
bail!("invalid daemon name {name:?}; use letters, numbers, '.', '_' or '-'");
}
let (preset, version, mut table) = match declaration {
Declaration::Preset(version) => (Some(name.clone()), Some(version), toml::Table::new()),
Declaration::Definition(mut table) => {
let preset = take_string(&mut table, "preset")?;
let version = take_string(&mut table, "version")?;
(preset, version, table)
}
};
let daemon = if let Some(preset) = preset {
let version = version
.ok_or_else(|| eyre::eyre!("[daemons.{name}] requires version with preset"))?;
presets::expand(&name, &preset, &version, table, &source, &root)?
} else {
if version.is_some() || table.contains_key("options") {
bail!("[daemons.{name}] requires preset when specifying version or options");
}
if table.get("run").and_then(toml::Value::as_str).is_none() {View on GitHub (pinned to 533346cc37)