jdx/mise · error

`defaults {}` failed: {}

Error message

`defaults {}` failed: {}

What it means

Checking current state runs defaults read-type / defaults read. Their most common failure — key or domain absent — matches a regex ('does not exist', 'could not find key', 'Domain ... not found') and maps to a normal Unset state. Any other non-zero exit (cfprefsd unavailable, permission denied, corrupt plist, managed domain) misses the regex and bails with the joined args and stderr instead of masquerading the key as unset — the comment in the code says exactly that.

Source

Thrown at src/system/defaults.rs:227

        .stdin(Stdio::null())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .output()
        .await?;
    if !output.status.success() {
        // "does not exist" is the expected missing-key/-domain answer;
        // "could not find key" is the same for `read-type`;
        // "Domain [...] not found" is the expected answer when the domain does not exist;
        // any other failure (cfprefsd unavailable, managed domain, ...) must not
        // masquerade as Unset
        static MISSING_KEY_RE: LazyLock<Regex> = LazyLock::new(|| {
            Regex::new(r"(?i)does not exist|could not find key|Domain .* not found").unwrap()
        });
        let stderr = String::from_utf8_lossy(&output.stderr);
        if MISSING_KEY_RE.is_match(&stderr) {
            return Ok(None);
        }
        eyre::bail!(
            "`defaults {}` failed: {}",
            shell_words::join(args),
            stderr.trim()
        );
    }
    // strip only the trailing newline — leading/trailing spaces can be
    // significant in string values
    let stdout = String::from_utf8_lossy(&output.stdout);
    Ok(Some(stdout.trim_end_matches(['\r', '\n']).to_string()))
}

#[cfg(test)]
mod tests {
    use super::*;

    fn val(s: &str) -> toml::Value {
        s.parse().unwrap()
    }

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Reproduce with the 'defaults read ...' command shown in the error to see the raw stderr
  2. Run bootstrap from a real GUI login session so cfprefsd is reachable
  3. For a corrupt plist: quit the owning app, remove ~/Library/Preferences/<domain>.plist, re-run mise bootstrap
Defensive patterns

Strategy: try-catch

Validate before calling

# preflight: is the preferences daemon reachable at all?
defaults read -g AppleLocale >/dev/null 2>&1 || echo 'cfprefsd unreachable — run bootstrap from a GUI login session'

Try / catch

Catch non-zero from mise bootstrap and inspect the defaults stderr inside the message: text matching 'does not exist', 'could not find key', or 'Domain ... not found' is a normal Unset; anything else means environment or plist trouble — retry once in a GUI session, and treat corrupt-plist errors as 'delete the plist and re-run'.

Prevention

When it happens

Trigger: defaults read failing outside the missing-key cases: no per-user cfprefsd reachable (pure SSH session, no GUI login), a corrupt ~/Library/Preferences plist, or a sandbox blocking IPC to the preferences daemon.

Common situations: CI or bootstrap over SSH on macOS before first GUI login; an app crash leaving a truncated plist; running inside a hardened sandbox that denies AppleEvents/preferences IPC.

Related errors


AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22). Data as JSON: /api/errors/91f2ce933ac9e8c2. Report an issue: GitHub.