{"record":{"id":"1f1ef029b989cbdb","repo":"jdx/mise","slug":"com-apple-dock-persistent-apps-is-not-an-array-left","errorCode":null,"errorMessage":"com.apple.dock persistent-apps is not an array; left unchanged","messagePattern":"com\\.apple\\.dock persistent-apps is not an array; left unchanged","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/defaults/dock.rs","lineNumber":73,"sourceCode":"        .as_dictionary()?\n        .get(\"_CFURLString\")?\n        .as_string()?;\n    let path = if location.starts_with('/') {\n        PathBuf::from(location)\n    } else {\n        url::Url::parse(location).ok()?.to_file_path().ok()?\n    };\n    if !path.is_absolute() || !path.extension()?.eq_ignore_ascii_case(\"app\") {\n        return None;\n    }\n    Some(path.components().collect())\n}\n\nfn tiles(value: Option<&plist::Value>) -> Result<&[plist::Value]> {\n    match value {\n        None => Ok(&[]),\n        Some(plist::Value::Array(tiles)) => Ok(tiles),\n        Some(_) => eyre::bail!(\"com.apple.dock persistent-apps is not an array; left unchanged\"),\n    }\n}\n\npub(super) fn matches(value: &DefaultsValue, current: &plist::Value) -> Result<bool> {\n    Ok(paths(value)?\n        .iter()\n        .map(|path| crate::file::canonicalize_or_self(path))\n        .eq(tiles(Some(current))?\n            .iter()\n            .filter_map(app_path)\n            .map(|path| crate::file::canonicalize_or_self(&path))))\n}\n\n#[cfg(any(target_os = \"macos\", test))]\npub(super) fn reconcile(\n    value: &DefaultsValue,\n    current: Option<&plist::Value>,\n) -> Result<plist::Value> {","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/defaults/dock.rs#L55-L91","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"let current = read_plist(\"com.apple.dock\", \"persistent-apps\");\nif !matches!(current, Some(plist::Value::Array(_)) | None) {\n    eprintln!(\"persistent-apps has unexpected type; reset the Dock before reconciling\");\n}","typeGuard":"fn is_plist_array(v: Option<&plist::Value>) -> bool {\n    matches!(v, None | Some(plist::Value::Array(_)))\n}","tryCatchPattern":"match dock::matches(&desired, &current) {\n    Err(e) if e.to_string().contains(\"not an array\") => {\n        eprintln!(\"Skipping dock reconcile: persistent-apps corrupted; run `defaults delete com.apple.dock persistent-apps && killall Dock`\");\n    }\n    r => r?,\n}","preventionTips":["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."],"tags":["macos","dock","plist","unexpected-shape"],"backgroundTag":"unexpected-response-shape","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}