Skip to content

Instantly share code, notes, and snippets.

@romellem
Last active February 27, 2024 00:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save romellem/dcaba2d57d246420f600b7cfeb4b0cdd to your computer and use it in GitHub Desktop.
Save romellem/dcaba2d57d246420f600b7cfeb4b0cdd to your computer and use it in GitHub Desktop.
Fix homebrew node installations - dyld: Library not loaded: /usr/local/opt/icu4c/lib/$VERSION

On my unsupported macOS (currently 10.14), whenever I brew upgrade, node breaks with the following error

$ node -v
dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.69.dylib
  Referenced from: /usr/local/opt/node@16/bin/node
  Reason: image not found

If you ls in the /usr/local/opt/icu4c/lib/ directory, you'll see a different version, e.g. libicui18n.71.dylib or whatever.

I always fumble around trying to fix this, so here is what I think should be fairly stable instructions for how to resolve this issue.

1. Create a new tap

Homebrew has a command to create a new tap (which is just a git repo) on your local machine. You need to give it a namespace, and a name.

$ brew tap-new namespace/name

Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/namespace/name/.git/

2. Extract the old formula into the new tap

Now, you'll be able to extract the old formula into this new tap.

In my example, I needed version 69.1 of icu4c. So my command was

$ brew extract --version=69.1 icu4c namespace/name

Swap namespace and name with whatever you picked before.

3. Reinstall the newly extracted formula

Now you have an .rb file that can install your version, but it probably won't link things correctly. That's OK, we'll be able to manually fix this later.

Run the reinstall command with your custom tap, the formula with version number, and the --build-from-source flag.

$ brew reinstall namespace/name/icu4c@69.1 --build-from-source

If that works, you should see a message similar to

icu4c@69.1 is keg-only, which means it was not symlinked into /usr/local,
because macOS provides libicucore.dylib (but nothing else).

If you need to have icu4c@69.1 first in your PATH, run:
  echo 'export PATH="/usr/local/opt/icu4c@69.1/bin:$PATH"' >> ~/.zshrc
  echo 'export PATH="/usr/local/opt/icu4c@69.1/sbin:$PATH"' >> ~/.zshrc

For compilers to find icu4c@69.1 you may need to set:
  export LDFLAGS="-L/usr/local/opt/icu4c@69.1/lib"
  export CPPFLAGS="-I/usr/local/opt/icu4c@69.1/include"

For pkg-config to find icu4c@69.1 you may need to set:
  export PKG_CONFIG_PATH="/usr/local/opt/icu4c@69.1/lib/pkgconfig"

4. Manually link new files

For whatever reason, I never was able to get brew link to work. I'd get this error:

$ brew link --force namespace/name/icu4c@69.1

Warning: Refusing to link macOS provided/shadowed software: icu4c@69.1

So instead, I just manually created the symlink.

When the reinstall finishes, you'll see the location of the install, e.g. /usr/local/opt/icu4c@69.1/. So you just need to symlink this over /usr/local/opt/icu4c/, the non versioned folder.

$ ln -nfs /usr/local/opt/icu4c@69.1 /usr/local/opt/icu4c
# If you get an access denied error, you may have to `sudo` the above command

Since the /usr/local/opt/icu4c folder already exists, you'll want to overwrite it, hence the -nf flags.

That's it! You should now have a working node version again.

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