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
- Reset the Dock to a known-good state: `defaults delete com.apple.dock persistent-apps; killall Dock`, then rerun reconciliation.
- Fix the value manually to be a plist array (`defaults write com.apple.dock persistent-apps -array ...`) before letting the tool manage it.
- 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, ¤t) {
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
- Don't write scalars to persistent-apps with `defaults write -string`.
- Reset the Dock (`defaults delete com.apple.dock persistent-apps; killall Dock`) before adopting management tooling.
- Snapshot/backup the dock plist before letting tools rewrite it.
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
- [bootstrap.macos.dock].apps: expected a path relative to…
- [bootstrap.macos.dock].apps: expected an absolute or ~/…
- [bootstrap.macos.dock].apps: expected an array of…
- defaults patch path must not be empty
- Dock application is unavailable
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)