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

  1. Check mount options for the prefix path (ro, root_squash) and move the prefix to a normal local filesystem
  2. Inspect extended attributes and ACLs (lsattr, getfacl) and clear immutable/read-only flags
  3. 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

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


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/11b96da1b2f5642d. Report an issue: GitHub.