Skip to content

Fix: Install casks individually to handle partial download failures (#288)#294

Open
MaximilianPavon wants to merge 1 commit intobuo:masterfrom
MaximilianPavon:fix/partial-download-failures
Open

Fix: Install casks individually to handle partial download failures (#288)#294
MaximilianPavon wants to merge 1 commit intobuo:masterfrom
MaximilianPavon:fix/partial-download-failures

Conversation

@MaximilianPavon
Copy link

Summary

Fixes #288 - When some downloads fail during brew cu --all, remaining casks are now still installed and the command exits with a non-zero code.

Problem

Previously, all casks were installed in a single batch brew reinstall command. When Homebrew 5.x pre-fetches downloads and any fail, it aborts the entire operation without installing successfully downloaded casks. The command also always exited with code 0 regardless of failures.

Solution

  • Pre-fetch downloads in parallel using brew fetch --cask to maintain fast download performance
  • Install each cask individually so failed downloads don't block successful ones
  • Track successful and failed installations separately
  • Exit with code 1 when any installation fails
  • Report failed casks at the end of the upgrade process

Testing

Tested manually on a network that blocks certain download URLs (corporate VPN). Verified that:

  • ✅ Successfully downloaded casks are installed
  • ✅ Failed downloads don't prevent other casks from installing
  • ✅ Exit code is 1 when any cask fails
  • ✅ Failed casks are reported at the end

Example Output

Details
brew cu --all
==> Options
Include auto-update (-a): true
Include latest (-f): false
==> Updating Homebrew
==> Updating Homebrew...
Already up-to-date.
==> Finding outdated apps
       Cask                   Current         Latest         A/U    Result
 1/34  alt-tab                8.0.0           8.0.0           Y   [   OK   ]
 2/34  bettertouchtool@alpha  6.034           6.034           Y   [   OK   ]
 3/34  chatgpt                1.2025.350      1.2025.350      Y   [   OK   ]
 4/34  claude                 1.0.3218        1.0.3218        Y   [   OK   ]
 5/34  claude-code            2.1.7           2.1.7               [   OK   ]
 6/34  coconutbattery         4.2.0           4.2.0           Y   [   OK   ]
 7/34  cursor                 2.3.35          2.3.35          Y   [   OK   ]
 8/34  daisydisk              4.33.2          4.33.2          Y   [   OK   ]
 9/34  deepl                  25.12.13413558  26.1.13531937   Y   [ FORCED ]
10/34  detectx-swift          1.0982          1.0982          Y   [   OK   ]
11/34  font-hack-nerd-font    3.4.0           3.4.0               [   OK   ]
12/34  ghostty                1.2.3           1.2.3           Y   [   OK   ]
13/34  istat-menus            7.20            7.20            Y   [   OK   ]
14/34  iterm2                 3.6.6           3.6.6           Y   [   OK   ]
15/34  itermbrowserplugin     1.0             1.0                 [   OK   ]
16/34  itsycal                0.15.10         0.15.10         Y   [   OK   ]
17/34  keepassxc              2.7.11          2.7.11              [   OK   ]
18/34  knockknock             4.0.3           4.0.3               [   OK   ]
19/34  logi-options+          1.98.824948     1.98.824948     Y   [   OK   ]
20/34  logitech-g-hub         2025.9.824733   2025.9.824733   Y   [   OK   ]
21/34  mathpix-snipping-tool  3.4.16.2        3.4.16.2        Y   [   OK   ]
22/34  miniconda              base            py313_25.11.1   Y   [   OK   ]
23/34  obsidian               1.11.4          1.11.4          Y   [   OK   ]
24/34  ollama-app             0.14.0          0.14.0          Y   [   OK   ]
25/34  podman-desktop         1.24.2          1.24.2          Y   [   OK   ]
26/34  postman                11.80.0         11.80.2         Y   [ FORCED ]
27/34  pycharm                2025.3.1.1      2025.3.1.1      Y   [   OK   ]
28/34  pycharm-ce             2025.2.5        2025.2.5        Y   [   OK   ]
29/34  shortcat               0.12.2          0.12.2          Y   [   OK   ]
30/34  sourcetree             4.2.16          4.2.16          Y   [   OK   ]
31/34  spotify                1.2.79.427      1.2.79.427      Y   [   OK   ]
32/34  sublime-text           4200            4200            Y   [   OK   ]
33/34  visual-studio-code     1.108.0         1.108.0         Y   [   OK   ]
34/34  zed                    0.218.7         0.218.7         Y   [   OK   ]
==> Found outdated apps
     Cask     Current         Latest         A/U    Result
1/2  deepl    25.12.13413558  26.1.13531937   Y   [ FORCED ]
2/2  postman  11.80.0         11.80.2         Y   [ FORCED ]

Do you want to upgrade 2 apps or enter [i]nteractive mode [y/i/N]? y
==> Upgrading 2 apps
==> Fetching downloads for: deepl and postman
Fetching: deepl, postman
✔︎ Cask postman (11.80.2)                                                                                                                                   Verified    122.2MB/122.2MB
✘ Cask deepl (26.1.13531937)
Error: Download failed on Cask 'deepl' with message: Download failed: https://www.deepl.com/macos/download/26.1/13531937/DeepL.dmg
==> Fetching downloads for: deepl
✘ Cask deepl (26.1.13531937)
Error: Download failed on Cask 'deepl' with message: Download failed: https://www.deepl.com/macos/download/26.1/13531937/DeepL.dmg
Error: Failed to upgrade deepl
==> Fetching downloads for: postman
✔︎ Cask postman (11.80.2)                                                                                                                                   Verified    122.2MB/122.2MB
==> Uninstalling Cask postman
==> Backing App 'Postman.app' up to '/opt/homebrew/Caskroom/postman/11.80.0/Postman.app'
==> Removing App '/Applications/Postman.app'
Password:
==> Purging files for version 11.80.0 of Cask postman
==> Installing Cask postman
==> Moving App 'Postman.app' to '/Applications/Postman.app'
🍺  postman was successfully installed!
Error: Failed to upgrade: deepl

Fixes buo#288

Previously, all casks were installed in a single batch command. When
Homebrew 5.x pre-fetches downloads and any fail, it aborts the entire
operation without installing successfully downloaded casks.

Changes:
- Pre-fetch all casks in parallel using 'brew fetch' to maintain fast downloads
- Install each cask individually to handle partial failures gracefully
- Track successful and failed installations separately
- Only cleanup old versions for successfully installed casks
- Exit with code 1 when any installation fails
- Report which casks failed to upgrade at the end
@kerim
Copy link

kerim commented Feb 5, 2026

Eagerly awaiting this merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

When some downloads fail during brew cu --all it stops updating the remaining casks

2 participants