jdx/mise · error

com.apple.dock persistent-apps is not an array; left…

Error message

com.apple.dock persistent-apps is not an array; left unchanged

What it means

Raised by `dock::tiles` when the live `com.apple.dock` `persistent-apps` preference exists but is not a plist array. Since the library cannot safely interpret or rewrite a Dock layout with an unexpected shape, it refuses and leaves the Dock unchanged rather than corrupting it.

Solutions

  1. Reset the Dock to a known-good state: `defaults delete com.apple.dock persistent-apps; killall Dock`, then rerun reconciliation.
  2. Fix the value manually to be a plist array (`defaults write com.apple.dock persistent-apps -array ...`) before letting the tool manage it.
  3. Investigate which other tool rewrote the key as a scalar and stop it from doing so.
Defensive patterns

Strategy: type-guard

Validate before calling

let current = read_plist("com.apple.dock", "persistent-apps");
if !matches!(current, Some(plist::Value::Array(_)) | None) {
    eprintln!("persistent-apps has unexpected type; reset the Dock before reconciling");
}

Type guard

fn is_plist_array(v: Option<&plist::Value>) -> bool {
    matches!(v, None | Some(plist::Value::Array(_)))
}

Try / catch

match dock::matches(&desired, &current) {
    Err(e) if e.to_string().contains("not an array") => {
        eprintln!("Skipping dock reconcile: persistent-apps corrupted; run `defaults delete com.apple.dock persistent-apps && killall Dock`");
    }
    r => r?,
}

Prevention

When it happens

Trigger: Calling `matches` or `reconcile` against a current plist value read from `com.apple.dock persistent-apps` that is Some but not `plist::Value::Array` — e.g. the key was manually set to a string/blob or corrupted by another tool.

Common situations: Another tool or a manual `defaults write com.apple.dock persistent-apps -string ...` replaced the array with a scalar; a corrupted preferences plist after a failed sync; restoring a plist backup with a different schema version.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/1f1ef029b989cbdb. Report an issue: GitHub.

Appendix: source

Thrown at src/system/defaults/dock.rs:73

        .as_dictionary()?
        .get("_CFURLString")?
        .as_string()?;
    let path = if location.starts_with('/') {
        PathBuf::from(location)
    } else {
        url::Url::parse(location).ok()?.to_file_path().ok()?
    };
    if !path.is_absolute() || !path.extension()?.eq_ignore_ascii_case("app") {
        return None;
    }
    Some(path.components().collect())
}

fn tiles(value: Option<&plist::Value>) -> Result<&[plist::Value]> {
    match value {
        None => Ok(&[]),
        Some(plist::Value::Array(tiles)) => Ok(tiles),
        Some(_) => eyre::bail!("com.apple.dock persistent-apps is not an array; left unchanged"),
    }
}

pub(super) fn matches(value: &DefaultsValue, current: &plist::Value) -> Result<bool> {
    Ok(paths(value)?
        .iter()
        .map(|path| crate::file::canonicalize_or_self(path))
        .eq(tiles(Some(current))?
            .iter()
            .filter_map(app_path)
            .map(|path| crate::file::canonicalize_or_self(&path))))
}

#[cfg(any(target_os = "macos", test))]
pub(super) fn reconcile(
    value: &DefaultsValue,
    current: Option<&plist::Value>,
) -> Result<plist::Value> {

View on GitHub (pinned to 533346cc37)