jdx/mise · error
duplicate Dock application
Error message
duplicate Dock application: {} What it means
Thrown by dock::paths when two entries in [bootstrap.macos.dock].apps resolve to the same Dock application. Each path is normalized (components collected, canonicalized via canonicalize_or_self) and inserted into a set; a duplicate insert fails, since patching the same app twice into the Dock would be ambiguous.
Solutions
- Remove the duplicate entry from the apps array
- If one path is a symlink to another listed app, keep only the canonical path
- Deduplicate merged config layers so each app appears once
Example fix
// before apps = ["/Applications/Safari.app", "/Applications/./Safari.app"] // after apps = ["/Applications/Safari.app"]
Defensive patterns
Strategy: validation
Validate before calling
fn validate_no_dock_duplicates(values: &[String]) -> Result<(), String> {
let mut seen = std::collections::HashSet::new();
for v in values {
let p: std::path::PathBuf = Path::new(v).components().collect();
let key = std::fs::canonicalize(&p).unwrap_or_else(|_| p.clone());
if !seen.insert(key) {
return Err(format!("duplicate Dock application: {v}"));
}
}
Ok(())
} Prevention
- Deduplicate the apps array (on canonical paths) before applying
- Avoid listing both a symlink and its target for the same app
- When merging config layers, union dock apps by canonical path
When it happens
Trigger: The same .app listed twice in dock.apps, or two paths that canonicalize identically (e.g. "/Applications/Foo.app" and "/Applications/./Foo.app", or a symlink resolving to an already-listed app).
Common situations: Listing an app via both a symlink (e.g. ~/Applications alias) and its real location; merging config layers that each add the same app; copy-paste duplicates in the apps array.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
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…
- brew-cask: duplicate app target
- com.apple.dock persistent-apps is not an array; left…
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/fc34c653f1e6404a.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/defaults/dock.rs:36
eyre::ensure!(
!Path::new(rest).has_root(),
"[bootstrap.macos.dock].apps: expected a path relative to home: {value}"
);
crate::env::HOME.join(rest)
} else {
PathBuf::from(value)
};
eyre::ensure!(
path.is_absolute()
&& path
.extension()
.is_some_and(|ext| ext.eq_ignore_ascii_case("app"))
&& !path.components().any(|c| matches!(c, Component::ParentDir))
&& !value.contains('\0'),
"[bootstrap.macos.dock].apps: expected an absolute or ~/ application path: {value}"
);
let path: PathBuf = path.components().collect();
eyre::ensure!(
seen.insert(crate::file::canonicalize_or_self(&path)),
"duplicate Dock application: {}",
path.display()
);
paths.push(path);
}
Ok(paths)
}
fn app_path(tile: &plist::Value) -> Option<PathBuf> {
let tile = tile.as_dictionary()?;
if tile.get("tile-type")?.as_string()? != "file-tile" {
return None;
}
let location = tile
.get("tile-data")?
.as_dictionary()?
.get("file-data")?View on GitHub (pinned to 533346cc37)