jdx/mise · error
font target is outside the platform font directory
Error message
font target is outside the platform font directory: {} What it means
Font targets in a cask receipt must be File-kind records located inside the platform font directory (~/Library/Fonts on macOS) whose contents match the staged copy in the version dir (checked by stripping the font-dir prefix and comparing fingerprints). If the font path is outside the font directory or the staged file no longer matches, mise refuses to prune the cask to avoid deleting fonts it cannot prove it owns.
Solutions
- Reinstall the cask with mise (uninstall + install) so font paths and fingerprints are re-recorded against the current font directory
- Restore the font to its recorded path under the platform font directory, or update the environment so font_dir() matches where fonts were installed
- Replace the modified font file with the original so the staged fingerprint matches, then retry the prune
- Skip pruning this cask and remove fonts manually or via brew
Example fix
// before: font moved out of the font dir, fingerprint mismatch ~/Fonts/Custom/Foo.ttf // not below font_dir() as recorded // after: restore location and reinstall to regenerate receipt mv ~/Fonts/Custom/Foo.ttf ~/Library/Fonts/Foo.ttf mise uninstall brew-cask:foo && mise install brew-cask:foo
Defensive patterns
Strategy: validation
Validate before calling
// pre-flight: font targets must be files under the platform font dir
fn fonts_in_font_dir(receipt: &CaskReceipt) -> bool {
let fonts = font_dir();
receipt.fonts.iter().all(|p| {
path_is_below(p, &fonts)
&& p.metadata().map(|m| m.is_file()).unwrap_or(false)
})
} Type guard
fn font_target_is_safe(path: &Path, fonts: &Path) -> bool {
path.is_file()
&& path_is_below(path, fonts)
&& path.strip_prefix(fonts).is_ok()
} Try / catch
match apply_cask_prune_plan_in(&plan) {
Ok(removed) => info!("pruned {removed} casks"),
Err(e) if e.to_string().contains("outside the platform font directory") => {
warn!("font moved or modified; reinstalling cask: {e:#}");
// restore font location or fall back to manual removal
}
Err(e) => return Err(e),
} Prevention
- Don't move cask-installed fonts out of the platform font directory recorded at install time
- Use the same --fontdir setting (if any) for installing and pruning environments
- Avoid editing or replacing font files after installation; fingerprints are compared against the staged copy
- Reinstall the cask via mise whenever font locations or contents change
When it happens
Trigger: Calling cask_prune_plan_from_tokens or apply_cask_prune_plan_in when a receipt.fonts path is not below font_dir() (e.g. font moved to a custom fontdir), the record's kind is not File, or the staged font under candidate.version_dir differs from the installed file (edited, replaced, or re-downloaded variant).
Common situations: User moved a cask font into a custom fonts directory via HOMEBREW_CASK_OPTS --fontdir; the font file was modified or replaced after install so fingerprints diverge; receipts written under a different fontdir setting than the pruning run uses.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- app target is outside an allowed Applications directory
- binary target is not an owned Caskroom symlink
- app Info.plist must be a regular file
- artifact target has changed
- brew-cask: ' ' must stay below Applications
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/fa016d463fa63232.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/packages/brew/cask/state.rs:1109
{
bail!(
"binary target is not an owned Caskroom symlink: {}",
path.display()
);
}
}
for path in &receipt.fonts {
let record = records
.get(path)
.ok_or_else(|| eyre!("missing font target record"))?;
let fonts = font_dir();
if record.fingerprint.kind != CaskTargetKind::File
|| !path_is_below(path, &fonts)
|| !path.strip_prefix(&fonts).is_ok_and(|relative| {
staged_target_matches(record, &candidate.version_dir.join(relative))
})
{
bail!(
"font target is outside the platform font directory: {}",
path.display()
);
}
}
let completion_roots = [
CompletionShell::Bash,
CompletionShell::Fish,
CompletionShell::Zsh,
CompletionShell::Pwsh,
]
.map(default_completion_dir);
for path in &receipt.completions {
let record = records
.get(path)
.ok_or_else(|| eyre!("missing completion target record"))?;
if record.fingerprint.kind != CaskTargetKind::Symlink
|| !completion_rootsView on GitHub (pinned to 533346cc37)