jdx/mise · error · eyre::Report
{} is still not writable after bootstrap
Error message
{} is still not writable after bootstrap What it means
After running sudo mkdir -p and sudo chown -R on the Homebrew prefix, mise re-checks that the prefix is actually writable by the invoking user. If the writability probe still fails, bootstrap could not produce a usable prefix and the error names the path that is stuck. This is an environment-level failure: the chown succeeded as a command but the filesystem still denies writes.
Source
Thrown at src/system/packages/brew/prefix.rs:229
let owner = if cfg!(target_os = "macos") {
format!("{user}:admin")
} else {
user
};
let mut mkdir_dirs: Vec<String> = vec![prefix.to_string_lossy().to_string()];
mkdir_dirs.extend(dirs.iter().map(|d| d.display().to_string()));
let mkdir_args: Vec<String> = ["-p".to_string()].into_iter().chain(mkdir_dirs).collect();
let chown_args: Vec<String> = vec!["-R".to_string(), owner, prefix.display().to_string()];
if dry_run {
miseprintln!("{}", sudo::argv("mkdir", &mkdir_args).join(" "));
miseprintln!("{}", sudo::argv("chown", &chown_args).join(" "));
return Ok(());
}
info!("creating {} (requires sudo once)", prefix.display());
sudo::run("mkdir", &mkdir_args, &[])?;
sudo::run("chown", &chown_args, &[])?;
if !writable(&prefix) {
bail!("{} is still not writable after bootstrap", prefix.display());
}
} else if dry_run {
// prefix is ours but subdirs are missing — show what a real run
// would create (no sudo needed)
for dir in &missing_subdirs {
miseprintln!("mkdir -p {}", dir.display());
}
} else {
// prefix is ours, just fill in missing subdirs
for dir in missing_subdirs {
crate::file::create_dir_all(&dir)?;
}
}
Ok(())
}
View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Check mount options for the prefix path (ro, root_squash) and move the prefix to a normal local filesystem
- Inspect extended attributes and ACLs (lsattr, getfacl) and clear immutable/read-only flags
- Manually create and chown the prefix as root, confirm your user can create a file there, then re-run `mise bootstrap packages apply`
Defensive patterns
Strategy: validation
Validate before calling
# pre-flight writability probe mirroring the post-bootstrap check
PREFIX="$HOME/.local/share/mise/brew" # or your configured brew prefix
mkdir -p "$PREFIX" 2>/dev/null
touch "$PREFIX/.mise-write-test" 2>/dev/null || { echo "$PREFIX not writable (ro mount / root_squash / MAC policy?)"; exit 1; }
rm -f "$PREFIX/.mise-write-test" Prevention
- Keep the brew prefix on a local, writable filesystem — not NFS with root_squash or read-only mounts
- Check lsattr/getfacl on the prefix when chown appears to succeed but writes still fail
- On hardened hosts, allow the sudo mkdir/chown in policy before running bootstrap
When it happens
Trigger: writable(&prefix) returns false immediately after the chown — read-only mounts, root-squashing NFS, SELinux/AppArmor denials, immutable file attributes, or ACLs that override the ownership change.
Common situations: Prefix located on an NFS export with root_squash; containers with read-only mounts; hardened systems where even root is constrained by MAC policy; disk mounted ro at runtime.
Related errors
- cannot determine the current user to own {}
- Unknown shim mode
- brew-cask: refusing elevated operation through mutable direc
- brew-cask: structured copy source must resolve to exactly on
- {err}. Creating directory symlinks on Windows may require ad
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/11b96da1b2f5642d.
Report an issue: GitHub.