You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
doctor: skip removed formulae in deprecated check - #24490
brew doctor told me to find a replacement for openssl@1.1 twice:
Warning: Some installed kegs have no formulae!
This means they were either deleted or installed manually.
You should find replacements for the following formulae:
terraform
go@1.14
grv
exa
unrar
openssl@1.1
six
python@3.8
packer
Warning: Some installed formulae are deprecated or disabled.
You should find replacements for the following formulae:
openssl@1.1
pcre
python@3.9
qt@5
The formula was removed from homebrew/core on 2025-10-25, so the first warning is the accurate one. The second comes from the keg. Once a formula is gone from its tap, Formula.installed loads the copy saved in the keg's .brew/ directory. My keg is from February 2023 and its copy already had deprecate! date: "2023-09-11", so it counts as deprecated. The copies in my other eight removed kegs have no deprecate! or disable!, so those appear only once. Whether a removed formula is listed twice only depends on when it was installed.
This skips formulae with any keg under the same name that Keg#deleted_formula? flags, because check_deleted_formula already reports them, as #24466 did for check_for_unlinked_but_not_keg_only. A name is no longer listed in both sections. openssl@1.1 drops out of the second list and pcre, python@3.9 and qt@5 stay. Two other cases are now listed under "no formulae" only: deprecated formulae installed from a local file, and deprecated formulae still in a tap that also have an older keg from a removed tap, while that keg is installed.
That leaves the first warning as the only explanation, and "either deleted or installed manually" undersells what we know. A keg's receipt records the tap it came from, and all nine of mine record homebrew/core, so none was installed manually. The warning now groups formulae by that tap. Deleted comes first, then untapped, then kegs with no recorded tap, and within each homebrew/* taps come before others, alphabetically:
Warning: Some installed kegs have no formulae!
You should find replacements for the following formulae.
Deleted from homebrew/core:
exa
go@1.14
grv
openssl@1.1
packer
python@3.8
six
terraform
unrar
Each header only says what's known. "Deleted from" needs the tap to be homebrew/core, installed or in DEPRECATED_OFFICIAL_TAPS, which brew tap already refuses as empty. Any other tap that isn't installed says "From untapped other/tap" instead, because its formula may still exist. A keg with no receipt, such as a leftover from an unfinished install, says "No tap recorded (possibly installed manually)". A formula with several kegs is listed once, under its newest keg that records a tap.
This goes by the keg's tap alone, without also requiring a deprecated copy. Only openssl@1.1 of my nine has one, and they were all deleted the same way.
To reproduce:
keg="$(brew --cellar)/removed-formula/1.0"
mkdir -p "$keg/.brew"
cat > "$keg/.brew/removed-formula.rb" <<'EOS'
class RemovedFormula < Formula
url "https://brew.sh/removed-formula-1.0.tar.gz"
deprecate! date: "2020-01-01", because: :unsupported
end
EOS
echo '{"source":{"tap":"homebrew/core","spec":"stable"}}' > "$keg/INSTALL_RECEIPT.json"
ln -s "$keg" "$(brew --prefix)/opt/removed-formula"
brew doctor check_deleted_formula check_deprecated_disabled
rm "$(brew --prefix)/opt/removed-formula"
rm -r "$(brew --cellar)/removed-formula"
Have you checked for other open Pull Requests for the same change?
Have you explained what your changes do? Performance claims (e.g. "this is faster") must include brew benchmark results.
Have you explained why you'd like these changes included, not just what they do?
For bug fixes, have you given step-by-step brew commands to reproduce the bug?
Have you written new tests (excluding integration tests)? Here's an example.
Have you successfully run brew lgtm (style, typechecking and tests) locally?
I did not use AI/LLM to create this PR, or I disclosed the tool/model below and reviewed its output; I did not attribute commits to AI and will answer maintainer questions and review comments myself without AI/LLM.
Claude Code (Claude Opus 5.5) traced why brew doctor listed the formula twice, wrote the change and its specs and verified them. The new specs for removed formulae fail without the change and pass with it. It ran the reproduction steps before and after the change, ran the new filter against my install and ran brew lgtm on the first commit, which passes, then the specs and brew style on the follow-ups.
No actionable comments were generated in the recent review.
Summary
Summary by CodeRabbit
Bug Fixes
Diagnostics no longer flag deprecated formulae when their only installed copies are deleted-formula kegs.
Deleted-formula reports sort affected kegs by scheme and version, and prefer entries with recorded taps when selecting one per formula.
Reports group affected formulae by source, distinguishing deleted formulae, untapped sources and kegs with no recorded tap.
Source-specific headings replace the generic explanation that missing formulae were deleted or installed manually.
The diagnostic checks now filter deprecated or disabled formulae using installed keg names and deleted-formula status. Deleted-formula findings select the newest keg per name and group remediation by recorded tap.
Changes: Diagnostic findings
Layer / File(s)
Summary
Deprecated formula filter Library/Homebrew/diagnostic.rb, Library/Homebrew/test/diagnostic_checks_spec.rb
The check omits a deprecated or disabled formula when none of its installed kegs has the same name and is a deleted-formula keg. Tests cover formulae still in a tap, removed formulae and taps, and old keg names.
The check selects the newest deleted-formula keg per name, sorts affected names and groups remediation for core or installed taps, untapped taps and kegs without a recorded tap. Tests cover tap sources, manual installs and multiple versions.
Merge Risk: Low · up to bdd44
After a reverse rename, brew doctor may omit the current formula’s deprecation warning. This narrow case is suitable for follow-up and does not block merging.
Pre-merge checks: 4
Check name
Status
Explanation
Title check
The title identifies the change to the deprecated formula check.
Description check
The description covers the changes. It says any deleted keg triggers exclusion, but the file summary says every installed keg with the same name must be marked deleted.
Linked Issues check
Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check
Check skipped because no linked issues were found for this pull request.
Recent review info
Run configuration
Source mode: Auto
Repository: Unavailable
Branch: Unavailable
File: No configuration file from this repository applied
Commit: Unavailable
Layers: Organization UI
Review profile: CHILL
Plan: Advanced
Run ID: 6ba185b8-60a6-491f-b5dc-d890177b7e11
Commits
Reviewing files that changed from the base of the PR and between b0bc032 and bdd44d7.
Files selected for processing: 1
Library/Homebrew/diagnostic.rb
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.
The reason will be displayed to describe this comment to others. Learn more.
Additional comments: 1
Library/Homebrew/diagnostic.rb-1227-1227: 1
1227-1227: Minor · Functional Correctness · Quick win
Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.
Preserve a warning when this check runs alone.
brew doctor check_deprecated_disabled does not run check_deleted_formula. If its only installed formula is deprecated and removed, this change makes the command report success without a warning. (raw.githubusercontent.com)
Keep the warning for an individual check, or include the deleted-formula check in that invocation.
Review info
Run configuration
Source mode: Auto
Repository: Unavailable
Branch: Unavailable
File: No configuration file from this repository applied
Commit: Unavailable
Layers: Organization UI
Review profile: CHILL
Plan: Advanced
Run ID: 481ccd69-68fa-4ce2-9c4a-e60f7ac13dce
Commits
Reviewing files that changed from the base of the PR and between 944ccca and 51f631c.
Files selected for processing: 2
Library/Homebrew/diagnostic.rb
Library/Homebrew/test/diagnostic_checks_spec.rb
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Review info
Run configuration
Source mode: Auto
Repository: Unavailable
Branch: Unavailable
File: No configuration file from this repository applied
Commit: Unavailable
Layers: Organization UI
Review profile: CHILL
Plan: Advanced
Run ID: 29a4bbc4-13e1-41bc-b618-4cf58b06d333
Commits
Reviewing files that changed from the base of the PR and between 944ccca and 51f631c.
Files selected for processing: 2
Library/Homebrew/diagnostic.rb
Library/Homebrew/test/diagnostic_checks_spec.rb
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Review info
Run configuration
Source mode: Auto
Repository: Unavailable
Branch: Unavailable
File: No configuration file from this repository applied
Commit: Unavailable
Layers: Organization UI
Review profile: CHILL
Plan: Advanced
Run ID: 05e22009-71c7-4ace-812b-a57026702457
Commits
Reviewing files that changed from the base of the PR and between 51f631c and 02e0cad.
Files selected for processing: 2
Library/Homebrew/diagnostic.rb
Library/Homebrew/test/diagnostic_checks_spec.rb
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.
The reason will be displayed to describe this comment to others. Learn more.
I think this is fairly good but might be worth improving the "removed" language to indicate they were deleted by homebrew/core if they were also showing up as deprecated and from homebrew/core.
The reason will be displayed to describe this comment to others. Learn more.
Additional comments: 1
Library/Homebrew/diagnostic.rb-1470-1470: 1
1470-1470: Minor · Functional Correctness · Quick win
Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.
Select the newest keg before preferring a recorded tap.
When a newer untapped keg and an older core keg share a name, this sort selects the older core keg. The warning then places the name under “Deleted from homebrew/core” rather than describing the newest installation. The half-installed fixture confirms this result. Put scheme_and_version before tap presence in the sort key, and update that expectation. (raw.githubusercontent.com)
Review info
Run configuration
Source mode: Auto
Repository: Unavailable
Branch: Unavailable
File: No configuration file from this repository applied
Commit: Unavailable
Layers: Organization UI
Review profile: CHILL
Plan: Advanced
Run ID: 3b0ca642-0fe7-44a6-91e9-4b9e81b26c4f
Commits
Reviewing files that changed from the base of the PR and between 7441212 and 4b7119d.
Files selected for processing: 2
Library/Homebrew/diagnostic.rb
Library/Homebrew/test/diagnostic_checks_spec.rb
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.
- `check_deleted_formula` already lists these kegs, so a removed formula
could appear in both sections with the same advice
- Their deprecated state comes from the keg's old `.brew/` copy, so the
overlap only depended on when the formula was installed
- `installed_kegs` also holds kegs under old names and aliases, so a
removed `asciigen` keg hid the deprecation of an installed `glyph`
- `check_deleted_formula` only reports `asciigen`, so `glyph` appeared
in neither section
- A keg's tab records `homebrew/core`, so it wasn't installed manually
and "either deleted or installed manually" undersells what we know
- `check_deprecated_disabled` now skips these formulae, so this is the
only warning left to explain why they went away
- Two findings from one check ran together under one `Warning:`, and
fixing that meant changing how `doctor` prints every check
- One finding grouped by tap says where each formula went without that
- Sort by type (deleted, untapped, no tap), then `homebrew/*` taps
before others, then alphabetically
- List a formula once, under the newest keg that records a tap
- Only say "Deleted from" for `homebrew/core` or an installed tap, as
the formula from an untapped tap may still exist
- A keg with no receipt can be a leftover, not a manual install
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
brew doctortold me to find a replacement foropenssl@1.1twice:The formula was removed from
homebrew/coreon 2025-10-25, so the first warning is the accurate one. The second comes from the keg. Once a formula is gone from its tap,Formula.installedloads the copy saved in the keg's.brew/directory. My keg is from February 2023 and its copy already haddeprecate! date: "2023-09-11", so it counts as deprecated. The copies in my other eight removed kegs have nodeprecate!ordisable!, so those appear only once. Whether a removed formula is listed twice only depends on when it was installed.This skips formulae with any keg under the same name that
Keg#deleted_formula?flags, becausecheck_deleted_formulaalready reports them, as #24466 did forcheck_for_unlinked_but_not_keg_only. A name is no longer listed in both sections.openssl@1.1drops out of the second list andpcre,python@3.9andqt@5stay. Two other cases are now listed under "no formulae" only: deprecated formulae installed from a local file, and deprecated formulae still in a tap that also have an older keg from a removed tap, while that keg is installed.That leaves the first warning as the only explanation, and "either deleted or installed manually" undersells what we know. A keg's receipt records the tap it came from, and all nine of mine record
homebrew/core, so none was installed manually. The warning now groups formulae by that tap. Deleted comes first, then untapped, then kegs with no recorded tap, and within eachhomebrew/*taps come before others, alphabetically:Each header only says what's known. "Deleted from" needs the tap to be
homebrew/core, installed or inDEPRECATED_OFFICIAL_TAPS, whichbrew tapalready refuses as empty. Any other tap that isn't installed says "From untapped other/tap" instead, because its formula may still exist. A keg with no receipt, such as a leftover from an unfinished install, says "No tap recorded (possibly installed manually)". A formula with several kegs is listed once, under its newest keg that records a tap.This goes by the keg's tap alone, without also requiring a deprecated copy. Only
openssl@1.1of my nine has one, and they were all deleted the same way.To reproduce:
brew benchmarkresults.brewcommands to reproduce the bug?brew lgtm(style, typechecking and tests) locally?Claude Code (Claude Opus 5.5) traced why
brew doctorlisted the formula twice, wrote the change and its specs and verified them. The new specs for removed formulae fail without the change and pass with it. It ran the reproduction steps before and after the change, ran the new filter against my install and ranbrew lgtmon the first commit, which passes, then the specs andbrew styleon the follow-ups.