Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error: undefined method `each' for nil #19142

Open
3 tasks done
pitsianis opened this issue Jan 23, 2025 · 7 comments
Open
3 tasks done

Error: undefined method `each' for nil #19142

pitsianis opened this issue Jan 23, 2025 · 7 comments
Labels
bug Reproducible Homebrew/brew bug help wanted We want help addressing this

Comments

@pitsianis
Copy link

pitsianis commented Jan 23, 2025

brew doctor output

Your system is ready to brew.

Verification

  • My "brew doctor output" above says Your system is ready to brew. and am still able to reproduce my issue.
  • I ran brew update twice and am still able to reproduce my issue.
  • This issue's title and/or description do not reference a single formula e.g. brew install wget. If they do, open an issue at https://github.com/Homebrew/homebrew-core/issues/new/choose instead.

brew config output

HOMEBREW_VERSION: 4.4.17
ORIGIN: https://github.com/Homebrew/brew
HEAD: 55f399c10dc7e6cc07497bdfccdecc96329e3b57
Last commit: 4 days ago
Branch: stable
Core tap JSON: 23 Jan 21:54 UTC
Core cask tap JSON: 23 Jan 21:54 UTC
HOMEBREW_PREFIX: /opt/homebrew
HOMEBREW_CASK_OPTS: []
HOMEBREW_DISPLAY: /private/tmp/com.apple.launchd.UBA4VAnDlk/org.xquartz:0
HOMEBREW_MAKE_JOBS: 12
Homebrew Ruby: 3.3.7 => /opt/homebrew/Library/Homebrew/vendor/portable-ruby/3.3.7/bin/ruby
CPU: dodeca-core 64-bit arm_blizzard_avalanche
Clang: 16.0.0 build 1600
Git: 2.48.1 => /opt/homebrew/bin/git
Curl: 8.7.1 => /usr/bin/curl
macOS: 15.2-arm64
CLT: 16.2.0.0.1.1733547573
Xcode: N/A
Rosetta 2: false

What were you trying to do (and why)?

I tried to run this command

brew list python | xargs brew uninstall --force

What happened (include all command output)?

> brew list python | xargs brew uninstall --force
Error: undefined method `each' for nil
/opt/homebrew/Library/Homebrew/cask/cask_loader.rb:403:in `block in load'
/opt/homebrew/Library/Homebrew/cask/cask.rb:116:in `instance_eval'
/opt/homebrew/Library/Homebrew/cask/cask.rb:116:in `refresh'
/opt/homebrew/Library/Homebrew/cask/cask.rb:109:in `config='
/opt/homebrew/Library/Homebrew/cask/cask.rb:88:in `initialize'
/opt/homebrew/Library/Homebrew/cask/cask_loader.rb:338:in `new'
/opt/homebrew/Library/Homebrew/cask/cask_loader.rb:338:in `load'
/opt/homebrew/Library/Homebrew/cask/cask_loader.rb:139:in `load'
/opt/homebrew/Library/Homebrew/cask/cask_loader.rb:557:in `load'
/opt/homebrew/Library/Homebrew/cli/named_args.rb:366:in `block in load_formula_or_cask'
/opt/homebrew/Library/Homebrew/api.rb:203:in `with_no_api_env_if_needed'
/opt/homebrew/Library/Homebrew/cli/named_args.rb:320:in `load_formula_or_cask'
/opt/homebrew/Library/Homebrew/cli/named_args.rb:83:in `block in to_formulae_and_casks'
/opt/homebrew/Library/Homebrew/cli/named_args.rb:81:in `each'
/opt/homebrew/Library/Homebrew/cli/named_args.rb:81:in `flat_map'
/opt/homebrew/Library/Homebrew/cli/named_args.rb:81:in `to_formulae_and_casks'
/opt/homebrew/Library/Homebrew/cli/named_args.rb:279:in `to_kegs_to_casks'
/opt/homebrew/Library/Homebrew/cmd/uninstall.rb:44:in `run'
/opt/homebrew/Library/Homebrew/brew.rb:94:in `<main>'
Please report this issue:
  https://docs.brew.sh/Troubleshooting

What did you expect to happen?

I was expecting to remove all python installations

Step-by-step reproduction instructions (by running brew commands)

> brew update
==> Updating Homebrew...
Already up-to-date.
> brew update
==> Updating Homebrew...
Already up-to-date.
nikos@NP-MBPro-M2-3 /u/l/bin> brew doctor
Your system is ready to brew.
> brew list python | xargs brew uninstall --force
@pitsianis pitsianis added the bug Reproducible Homebrew/brew bug label Jan 23, 2025
@alebcay
Copy link
Member

alebcay commented Jan 23, 2025

The error message notwithstanding, brew list python | xargs brew uninstall --force won't achieve your desired goal of removing all python installations. brew list will show the files corresponding to a package, not a list of packages matching a search query.

$ brew list python
brew list python
/opt/homebrew/Cellar/python@3.13/3.13.1/bin/idle3
/opt/homebrew/Cellar/python@3.13/3.13.1/bin/idle3.13
/opt/homebrew/Cellar/python@3.13/3.13.1/bin/pip3
/opt/homebrew/Cellar/python@3.13/3.13.1/bin/pip3.13
/opt/homebrew/Cellar/python@3.13/3.13.1/bin/pydoc3
/opt/homebrew/Cellar/python@3.13/3.13.1/bin/pydoc3.13
/opt/homebrew/Cellar/python@3.13/3.13.1/bin/python3
/opt/homebrew/Cellar/python@3.13/3.13.1/bin/python3-config
/opt/homebrew/Cellar/python@3.13/3.13.1/bin/python3.13
/opt/homebrew/Cellar/python@3.13/3.13.1/bin/python3.13-config
/opt/homebrew/Cellar/python@3.13/3.13.1/bin/wheel3
/opt/homebrew/Cellar/python@3.13/3.13.1/bin/wheel3.13
/opt/homebrew/Cellar/python@3.13/3.13.1/Frameworks/Python.framework/ (3272 files)
/opt/homebrew/Cellar/python@3.13/3.13.1/IDLE 3.app/Contents/ (8 files)
/opt/homebrew/Cellar/python@3.13/3.13.1/lib/pkgconfig/ (4 files)
/opt/homebrew/Cellar/python@3.13/3.13.1/libexec/bin/ (6 files)
/opt/homebrew/Cellar/python@3.13/3.13.1/libexec/wheel-0.45.1-py3-none-any.whl
/opt/homebrew/Cellar/python@3.13/3.13.1/Python Launcher 3.app/Contents/ (16 files)
/opt/homebrew/Cellar/python@3.13/3.13.1/sbom.spdx.json
/opt/homebrew/Cellar/python@3.13/3.13.1/share/man/ (2 files)

You can add a -t flag on your xargs command to see the command that it is trying to run - this list of files is being passed in as an argument to brew uninstall, while brew uninstall is expecting package names.

$ brew list python | xargs -t brew uninstall --force
brew uninstall --force --verbose --debug /opt/homebrew/Cellar/python@3.13/3.13.1/INSTALL_RECEIPT.json /opt/homebrew/Cellar/python@3.13/3.13.1/LICENSE /opt/homebrew/Cellar/python@3.13/3.13.1/bin/pydoc3.13 /opt/homebrew/Cellar/python@3.13/3.13.1/bin/wheel3 /opt/homebrew/Cellar/python@3.13/3.13.1/bin/python3 [...]

@MikeMcQuaid MikeMcQuaid added the help wanted We want help addressing this label Jan 24, 2025
@apainintheneck
Copy link
Contributor

From the stacktrace seems like it's trying to load a cask from the API and for some reason the JSON is missing the artifacts array.

json_cask[:artifacts].each do |artifact|

It's not obvious why the output of brew list python would be something that the code would try to load as a cask though.

@cho-m
Copy link
Member

cho-m commented Jan 26, 2025

As already mentioned, the exact command usage is wrong.

In this case, an error is expected; however, it looks like the existing exception should be caught and a more descriptive one should be raised instead (CaskUnreadableError or something else).


Specifically, API loader doesn't cleanly deal with arbitrary JSON files, e.g.

brew ruby -e 'Cask::CaskLoader.load("/opt/homebrew/Cellar/python@3.13/3.13.1/INSTALL_RECEIPT.json")'
/opt/homebrew/Library/Homebrew/cask/cask_loader.rb:403:in `block in load': undefined method `each' for nil (NoMethodError)
	from /opt/homebrew/Library/Homebrew/cask/cask.rb:116:in `instance_eval'

...brew info /opt/homebrew/Cellar/python@3.13/3.13.1/INSTALL_RECEIPT.json
Error: undefined method `each' for nil
Warning: Removed Sorbet lines from backtrace!
Rerun with `--verbose` to see the original backtrace

JSON files are attempted to be loaded as a Cask at:

if path.extname == ".json"
return FromAPILoader.new(token, from_json: JSON.parse(@content), path:).load(config:)

One option could be moving that line into the exception handling block afterward, which would then result in:

brew info /opt/homebrew/Cellar/python@3.13/3.13.1/INSTALL_RECEIPT.json
Error: Cask 'INSTALL_RECEIPT' is unreadable: undefined method `each' for nil

Though perhaps this input should have been rejected earlier on. Not familiar if API is supposed to work off arbitrary JSON files.

@apainintheneck
Copy link
Contributor

You're right that the original command was wrong but I'd have expected the failure to be better in this case. Also, nice working figuring out that the problem was the JSON file.

The current logic requires us to be able to load casks from JSON files since that is the only representation of a cask that was installed using the API. For formulae we just store the original Ruby file since that's included automatically with the bottle if I remember correctly. That being said I don't think we should be trying to load random JSON files as casks from file paths given by the user even though it's still occasionally needed internally. If my memory serves me, we try to use the original cask definition (from either a Ruby or JSON file) when uninstalling casks. I'm not sure where else it's used off the top of my head.

Did we ever get rid of the ability to install formulae directly from file paths? I remember there was some discussion about that sort of thing before but I don't remember what happened in the end. It'd be nice to prevent JSON file loading for the same reasons here.

@MikeMcQuaid
Copy link
Member

Did we ever get rid of the ability to install formulae directly from file paths? I remember there was some discussion about that sort of thing before but I don't remember what happened in the end.

We attempted a deprecation but it got backed out because it was very involved and no-one (read: me) was motivated enough to get it over the line again.

@apainintheneck
Copy link
Contributor

Yeah, maybe it's not worth the effort then.

@MikeMcQuaid
Copy link
Member

I think it probably still is but just worth noting it's a non-trivial lift. Might be a good candidate to try at the AGM...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Reproducible Homebrew/brew bug help wanted We want help addressing this
Projects
None yet
Development

No branches or pull requests

5 participants