Patching packages in Yarn berry

Charles Stover
3 min readJul 21, 2022

At one point, patching a package in Yarn was as simple as yarn patch <package-name> and following the prompts. Now, it’s riddled with unintuitive bugs. Let’s walk through it.

Patching the package

To prepare the package for patching, run yarn patch <package-name>. The command output should specify a temporary directory for you to edit. Make the desired changes to the package in that directory, then follow the subsequent command in the output: yarn patch-commit -s <directory>.

Verifying the results

Once you’ve executed the patch-commit command, you should now have a .yarn/patches directory with a file corresponding to your target package name and version.

Additionally, your root package.json file should now contain a resolutions property with a <package-name>@<version> key and patch:<package-name>@npm:<version>::__archiveUrl=<url>#.yarn/patches/<package-name>-npm-<version>-<hash>.patch value.

This used to be everything you needed to do to patch a package, but you may notice that absolutely no changes occur after yarn installing the new patch.

Fixing the range

Unintuitively, Yarn expects the range provided in package.json's resolutions key to match the range specified by dependencies. Typically, this is as simple as changing <package-name>@<range> to <package-name>@^<range>, but if the mere ^ does not resolve your issue, you may need to investigate what ranges are used to reference your target package by executing yarn why <package-name>.

Per the aforementioned GitHub issue, this should be the only change you need to make, but unfortunately this behavior has regressed at some stage in Yarn berry’s development cycle. When you yarn install now, you will run into this cryptic error:

Error: Patch locators must explicitly define their source

Defining your source

I had the unfortunate pleasure of deep-diving the Yarn berry source code to resolve this. Yarn uses a particularly complex regular expression to parse the value seen in the package.json’s resolutions value. At some point, the Yarn team made a breaking change to this parser, but did not change their patch command to match it.

The yarn patch-commit command created a value of patch:<package-name>@npm:<version>::<search>#<path>. The new…