Skip to content

Instantly share code, notes, and snippets.

@romellem
Last active February 27, 2024 00:51
Show Gist options
  • 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/[email protected] --build-from-source

If that works, you should see a message similar to

[email protected] 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 [email protected] first in your PATH, run:
  echo 'export PATH="/usr/local/opt/[email protected]/bin:$PATH"' >> ~/.zshrc
  echo 'export PATH="/usr/local/opt/[email protected]/sbin:$PATH"' >> ~/.zshrc

For compilers to find [email protected] you may need to set:
  export LDFLAGS="-L/usr/local/opt/[email protected]/lib"
  export CPPFLAGS="-I/usr/local/opt/[email protected]/include"

For pkg-config to find [email protected] you may need to set:
  export PKG_CONFIG_PATH="/usr/local/opt/[email protected]/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/[email protected]

Warning: Refusing to link macOS provided/shadowed software: [email protected]

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/[email protected]/. So you just need to symlink this over /usr/local/opt/icu4c/, the non versioned folder.

$ ln -nfs /usr/local/opt/[email protected] /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