jdx/mise · error
brew-cask: font artifact
Error message
brew-cask: font artifact '{}' was not staged What it means
link_font runs after stage_font should have copied the font into the caskroom. It requires caskroom_font.is_file() before performing the atomic swap into the user font directory (rename the old target aside, copy the new one in). If the caskroom path is missing or not a regular file at link time, it bails with the cask's font source name — protecting the swap from operating on nothing.
Solutions
- Uninstall the cask (or delete its caskroom version directory) and reinstall so stage_font runs cleanly end-to-end
- Verify the cask font source names an actual font file inside the archive
- Check the caskroom path from the error for a directory or symlink where the font should be, and clear it
- Re-run with MISE_DEBUG=1 to confirm whether stage_font executed at all
Example fix
# before: partial caskroom state $ mise brew install --cask font-x # link_font fails # after $ mise brew uninstall --cask font-x && mise brew install --cask font-x
Defensive patterns
Strategy: validation
Validate before calling
// After staging fonts, assert each caskroom font is a regular file before linking.
for font in &cask.artifacts.fonts {
let staged = caskroom_font_path(caskroom, font)?;
if !staged.is_file() {
return Err(eyre!("font '{}' not staged", font.source));
}
} Type guard
fn staged_font_is_file(caskroom: &Path, font: &FontArtifact) -> bool {
caskroom_font_path(caskroom, font).map(|p| p.is_file()).unwrap_or(false)
} Prevention
- Point font stanzas at real font files in the archive, never directories
- Reinstall the cask cleanly after any interrupted install instead of forcing a re-link
- Treat a missing staged font as a signal of partial caskroom state
When it happens
Trigger: stage_font never ran or its output vanished (caskroom cleaned mid-install); the font source resolved to a directory or symlink rather than a regular file; caskroom_font_path computed a different location than stage_font wrote (e.g. changed font target between staging and linking).
Common situations: Interrupted installs leaving partial caskroom state; cask font stanza pointing at a directory inside the archive; font archives with unexpected layouts.
Related errors
- brew-cask: binary artifact
- brew-cask: command wrapper
- brew-cask: font artifact
- brew-cask: binary artifact
- brew-cask: completion artifact
AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22).
Data as JSON: /api/errors/3b0d10b5f6a632da.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/packages/brew/cask.rs:2775
sudo::run("installer", &args, &[])
}
fn stage_font(stage: &Path, caskroom: &Path, font: &FontArtifact) -> Result<()> {
let caskroom_font = caskroom_font_path(caskroom, font)?;
file::remove_all(&caskroom_font)?;
if let Some(parent) = caskroom_font.parent() {
file::create_dir_all(parent)?;
}
let source = find_file_artifact(stage, &font.source)
.ok_or_else(|| eyre!("brew-cask: font artifact '{}' was not found", font.source))?;
copy_cask_artifact(&source, &caskroom_font)?;
Ok(())
}
fn link_font(caskroom: &Path, font: &FontArtifact) -> Result<()> {
let caskroom_font = caskroom_font_path(caskroom, font)?;
if !caskroom_font.is_file() {
bail!("brew-cask: font artifact '{}' was not staged", font.source);
}
let target = font_target_path(font)?;
if let Some(parent) = target.parent() {
file::create_dir_all(parent)?;
}
// Atomic swap: rename existing font aside before copying the new one so
// that a failure during copy leaves the old font intact.
let old_target = target.with_extension(format!(
"mise-old-{}",
crate::hash::hash_to_str(&target.display().to_string())
));
file::remove_all(&old_target)?;
if target.exists() {
file::rename(&target, &old_target)?;
}
if let Err(e) = copy_cask_artifact(&caskroom_font, &target) {
if old_target.exists() {
let _ = file::rename(&old_target, &target);View on GitHub (pinned to 6f52dcdf99)