jdx/mise · error
mode must be between 0000 and 7777
Error message
mode must be between 0000 and 7777
What it means
The mode field of managed files/directories is parsed by parse_mode(): optional "0o" prefix, then strict octal via u32::from_str_radix(_, 8), and the value must be <= 0o7777 (the 12-bit permission mask). Non-octal digits fail earlier with the wrapped "mode must be an octal string" error; this specific bail means the number parsed fine but exceeds 7777.
Source
Thrown at src/system/managed_files.rs:1210
fn validate_privileged_target(path: &Path) -> Result<PathBuf> {
if !path.is_absolute() {
bail!("managed system path must be absolute: {}", path.display());
}
let path = path.absolutize()?.to_path_buf();
if path == Path::new("/") {
bail!("refusing to manage the filesystem root");
}
Ok(path)
}
fn parse_mode(mode: Option<&str>, default: u32) -> Result<u32> {
let Some(mode) = mode else {
return Ok(default);
};
let mode = mode.strip_prefix("0o").unwrap_or(mode);
let parsed = u32::from_str_radix(mode, 8).wrap_err("mode must be an octal string")?;
if parsed > 0o7777 {
bail!("mode must be between 0000 and 7777");
}
Ok(parsed)
}
fn nonempty(field: &str, value: Option<String>) -> Result<Option<String>> {
match value {
Some(value) if value.trim().is_empty() => bail!("{field} must not be empty"),
Some(value) => Ok(Some(value)),
None => Ok(None),
}
}
fn desired_metadata(kind: &str, mode: u32, owner: Option<&str>, group: Option<&str>) -> String {
let mut desired = format!("{kind} mode {mode:04o}");
if let Some(owner) = owner {
desired.push_str(&format!(" owner {owner}"));
}
if let Some(group) = group {View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Use a 3-4 digit octal permission string: "0644", "0755", "0600"
- If copying from st_mode, keep only the low 12 permission bits
Example fix
# before
[bootstrap.files]
"/etc/app/app.conf" = { content = "...", mode = "100644" }
# after
[bootstrap.files]
"/etc/app/app.conf" = { content = "...", mode = "0644" } Defensive patterns
Strategy: validation
Validate before calling
let m = mode.strip_prefix("0o").unwrap_or(mode);
let parsed = u32::from_str_radix(m, 8).wrap_err("mode must be an octal string")?;
if parsed > 0o7777 {
return Err(eyre::eyre!("mode must be between 0000 and 7777"));
} Type guard
fn is_valid_mode_string(mode: &str) -> bool {
let m = mode.strip_prefix("0o").unwrap_or(mode);
!m.is_empty()
&& m.chars().all(|c| ('0'..='7').contains(&c))
&& u32::from_str_radix(m, 8).map(|v| v <= 0o7777).unwrap_or(false)
} Prevention
- Author modes as 4-digit octal with a leading zero ("0644")
- Never paste raw st_mode values that include file-type bits
When it happens
Trigger: mode = "0o10000" or any octal value above 0o7777; copy-pasting a full st_mode value that includes file-type bits (e.g. "100644" parses as octal but overflows the mask).
Common situations: Pasting stat/st_mode output into config; assuming mode is decimal; adding an extra digit to "0644".
Related errors
- managed system path must be absolute: {}
- {field} must not be empty
- deps run command cannot be empty
- duration must not be negative: {}
- Invalid date or duration: {s}. Expected formats: '2024-06-01
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/e28f064fcfe65906.
Report an issue: GitHub.