tl;dr brew reinstall <package> doesn’t reinstall the package’s dependencies.

brew reinstall ca-certificates

The longer version

I was setting up a fresh install of macOS today when I ran into an error installing Yarn that I’d not seen before.

$ asdf install yarn
--2023-08-09 15:20:53--  https://classic.yarnpkg.com/downloads/1.22.19/yarn-v1.22.19.tar.gz
Resolving classic.yarnpkg.com (classic.yarnpkg.com)... 3.24.66.78, 54.253.236.10
Connecting to classic.yarnpkg.com (classic.yarnpkg.com)|3.24.66.78|:443... connected.
ERROR: cannot verify classic.yarnpkg.com's certificate, issued by ‘CN=R3,O=Let's Encrypt,C=US’:
  Unable to locally verify the issuer's authority.
To connect to classic.yarnpkg.com insecurely, use `--no-check-certificate'.

I did some basic checks in the browser but everything looked normal. I was able to visit classic.yarnpkg.com and the certificate was valid but I still couldn’t install Yarn on the command line.

Searching the yarn plugin repo’s issues for that error showed an issue where other people were seeing the same error message in late 2021/early 2022.

One possible solution posted in January 2022 by Devin Canterberry was:

Make sure you’ve got the latest CA certificates in your system trust store.

In this case, it was a freshly setup machine running macOS Ventura 13.4.1 (c), which was released July 12th 2023, less than a month prior me experiencing the issue. I thought it was unlikely to solve the issue but I updated the OS to 13.5, released on July 24th, 2023. The issue was still present after updating.

The next port of call was seeing what Homebrew had to say. All of the dependencies and packages I use are installed using brew.

$ brew doctor
[…]

Warning: Broken symlinks were found. Remove them with `brew cleanup`:
  /usr/local/etc/gnutls/cert.pem
  /usr/local/etc/openssl@1.1/cert.pem
  /usr/local/etc/openssl@3/cert.pem

Now we’re getting somewhere!

I will note that this was on an Intel Mac, so the brew prefix is /usr/local/. On Apple Silicon the prefix is /opt/homebrew/. Keep that in mind if you’re debugging on your own system.

The first thing I try whenever I see issues in brew doctor output is to re-install the package that is mentioned.

$ brew reinstall openssl@3
==> Fetching openssl@3
==> Downloading
[]
==> Reinstalling openssl@3 
==> Pouring openssl@3--3.1.2.ventura.bottle.1.tar.gz
🍺  /usr/local/Cellar/openssl@3/3.1.2: 6,495 files, 30.0MB
==> Running `brew cleanup openssl@3`...

The output all looked normal, but the error persisted.

I saw this answer on StackOverflow for a similar issue but on Linux. Richard Whitehead suggested that the original author installs ca-certificates using apt-install.

While I hadn’t installed ca-certificates manually, it is a dependency of openssl@1.1 and openssl@3.

Dependencies for a formula can be found in the brew info output.

$ brew info openssl@3
==> openssl@3: stable 3.1.2 (bottled)
Cryptography and SSL/TLS Toolkit
https://openssl.org/
/opt/homebrew/Cellar/openssl@3/3.1.2 (6,495 files, 28.4MB) *
  Poured from bottle using the formulae.brew.sh API on 2023-08-03 at 10:14:56
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/openssl@3.rb
License: Apache-2.0
==> Dependencies
Required: ca-certificates ✔

Now that I certain about what the dependency’s name is, it can be reinstalled.

$ brew reinstall ca-certificates
==> Fetching ca-certificates
==> Downloading
[]
==> Reinstalling ca-certificates 
==> Pouring ca-certificates--2023-05-30.ventura.bottle.tar.gz
==> Regenerating CA certificate bundle from keychain, this may take a while...
🍺  /usr/local/Cellar/ca-certificates/2023-05-30: 3 files, 216.2KB
==> Running `brew cleanup ca-certificates`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).

Running brew doctor once again and this time there was no warnings, no output, and a successful return code.

The real key to solving this was understanding that brew reinstall <package> does not also reinstall any dependencies. It kind of makes sense that it works that way but it was still a bit unexpected and took some time to work out what was going on.