{"record":{"id":"fa016d463fa63232","repo":"jdx/mise","slug":"font-target-is-outside-the-platform-font-directory-fa016d","errorCode":null,"errorMessage":"font target is outside the platform font directory: {}","messagePattern":"font target is outside the platform font directory: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask/state.rs","lineNumber":1109,"sourceCode":"        {\n            bail!(\n                \"binary target is not an owned Caskroom symlink: {}\",\n                path.display()\n            );\n        }\n    }\n    for path in &receipt.fonts {\n        let record = records\n            .get(path)\n            .ok_or_else(|| eyre!(\"missing font target record\"))?;\n        let fonts = font_dir();\n        if record.fingerprint.kind != CaskTargetKind::File\n            || !path_is_below(path, &fonts)\n            || !path.strip_prefix(&fonts).is_ok_and(|relative| {\n                staged_target_matches(record, &candidate.version_dir.join(relative))\n            })\n        {\n            bail!(\n                \"font target is outside the platform font directory: {}\",\n                path.display()\n            );\n        }\n    }\n    let completion_roots = [\n        CompletionShell::Bash,\n        CompletionShell::Fish,\n        CompletionShell::Zsh,\n        CompletionShell::Pwsh,\n    ]\n    .map(default_completion_dir);\n    for path in &receipt.completions {\n        let record = records\n            .get(path)\n            .ok_or_else(|| eyre!(\"missing completion target record\"))?;\n        if record.fingerprint.kind != CaskTargetKind::Symlink\n            || !completion_roots","sourceCodeStart":1091,"sourceCodeEnd":1127,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/packages/brew/cask/state.rs#L1091-L1127","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before: font moved out of the font dir, fingerprint mismatch\n~/Fonts/Custom/Foo.ttf  // not below font_dir() as recorded\n// after: restore location and reinstall to regenerate receipt\nmv ~/Fonts/Custom/Foo.ttf ~/Library/Fonts/Foo.ttf\nmise uninstall brew-cask:foo && mise install brew-cask:foo","handlingStrategy":"validation","validationCode":"// pre-flight: font targets must be files under the platform font dir\nfn fonts_in_font_dir(receipt: &CaskReceipt) -> bool {\n    let fonts = font_dir();\n    receipt.fonts.iter().all(|p| {\n        path_is_below(p, &fonts)\n            && p.metadata().map(|m| m.is_file()).unwrap_or(false)\n    })\n}","typeGuard":"fn font_target_is_safe(path: &Path, fonts: &Path) -> bool {\n    path.is_file()\n        && path_is_below(path, fonts)\n        && path.strip_prefix(fonts).is_ok()\n}","tryCatchPattern":"match apply_cask_prune_plan_in(&plan) {\n    Ok(removed) => info!(\"pruned {removed} casks\"),\n    Err(e) if e.to_string().contains(\"outside the platform font directory\") => {\n        warn!(\"font moved or modified; reinstalling cask: {e:#}\");\n        // restore font location or fall back to manual removal\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["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"],"tags":["brew","cask","fonts","validation","filesystem"],"backgroundTag":"invalid-argument-value","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"}