You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I’m creating an image using the { text } input and want to use a custom font (not a system-installed font) via the the fontfile option, but can’t get it working. (Apologies in advance if I’m holding it wrong.)
When you searched for similar issues, what did you find that might be related?
#3778, #4523, and #4208. #4208 in particular seems to overlap a lot, but the discussion didn’t help me.
Please provide a minimal, standalone code sample, without other dependencies, that demonstrates this question
As an example, I downloaded this TTF font: https://github.com/propublica/weepeople/blob/master/weepeople.ttf
Set fontfile to point to it.
And tried various font values (WeePeople, WeePeople Regular, Wee People Regular, weepeople, etc.)
(The issue does not appear to be specific to this font file though, I’ve tried with various fonts with the same result.)
In all cases the fontfile appears to have no effect.
I tried setting FC_DEBUG=1 on the process running sharp. This caused FC_DEBUG=1 to be logged the first time sharp was called. But there was no other additional logging.
In case it’s relevant, some system info: Node.js 24.18.0 on macOS 15.7.7 (darwin-x64 versions of sharp/libvips via npm)
Please provide sample image(s) that help explain this question
Here’s what the code above produces, regardless of font/fontfile options:
NODE_DEBUG=sharp is moderately helpful in that it at least logs a warning if the fontfile path is inaccurate (SHARP 44421: unable to load fontfile), but even with the path correct, I still can’t get it to use the font for some reason 🤔
I was running inside an Astro file, so tried a plain old .js file I ran with node, but same result.
Here’s the full script I ran (basically the same as yours with a different fontfile path:
Pango defaults to the CoreText rendering and mapping backend on macOS. You could try to use the Fontconfig backend with the PANGOCAIRO_BACKEND="fontconfig" environment variable. See: #2399.
Thanks for checking, are you able to reproduce on any platform other than Intel-based macOS? Perhaps something is going wrong creating the prebuilt binaries? I took a look at the build logs and there is a compiler warning on macOS:
UPDATE: I hadn't see Kleis' comment when posting this (thanks to GitHub's annoyingly-laggy UI), so yes, PANGOCAIRO_BACKEND is probably your friend here.
I can confirm that running the script with PANGOCAIRO_BACKEND="fontconfig" produces the expected output on the Intel macOS.
are you able to reproduce on any platform other than Intel-based macOS?
I just tried on an M2 Mac and found new issues! 😄
> node test-script.js
Fontconfig error: Cannot load default config file: File not found
# script hung here and had to be exited manually> PANGOCAIRO_BACKEND="fontconfig" node test-script.js
Fontconfig error: Cannot load default config file: File not found
Fontconfig error: Cannot load default config file: File not found
# script hung here and had to be exited manually
(Edit: just clicked that the script hanging was on me for not catching the async error when await-ing the call to sharp)
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
</fontconfig>
I updated the script based on Using custom fonts from a ttf file #4208 (comment) to set the FONTCONFIG_FILE variable and running fc-cache before sharp() runs. (The path needs to be an absolute path from my tests, hence resolving it rather than just using the relative ./fonts.conf path.)
import{execSync}from'node:child_process';import{fileURLToPath}from'node:url';importsharpfrom'sharp';constconfigFilePath=fileURLToPath(newURL('./fonts.conf',import.meta.url));// Set environment variable for fontconfigprocess.env.FONTCONFIG_FILE=configFilePath;// Refresh the font cache with your custom fonts directoryexecSync('fc-cache -fv');awaitsharp({text: {text: 'example',width: 800,height: 800,font: 'WeePeople',fontfile: './src/assets/weepeople.ttf',},}).png().toFile('test.png');
I did still have to run with PANGOCAIRO_BACKEND="fontconfig" to get the expected output.
I guess it’s hard to know if that stuff is needed when building in a repo that needs to run in various environments (e.g. different dev machines + CI)? I’m not sure how I’d check if fonts.conf is missing and only do this when required.
Edit: I’m not 100% sure if the fc-cache step is needed. I tried running it in the terminal to reset it and then commented it out in the script. The script still produced the correct output. Not sure if that’s a) because the previous run of the script changed some state that persisted or b) because that step is not actually needed.
Does running brew install fontconfig on the ARM-based macOS also "fix" this, or at least provide enough basic plumbing for fontconfig? IIRC running fc-cache does things like scan for system fonts so probably isn't required when an explicit path to a font file is provided.
We can probably improve sharp a bit here by emiting a warning on macOS when using fontfile but PANGOCAIRO_BACKEND is unset.
Does running brew install fontconfig on the ARM-based macOS also "fix" this
Didn’t change anything for me, no. The basic script still errors with “Fontconfig error: Cannot load default config file: File not found” even after running brew install fontconfig and restarting the terminal session for good measure.
Activity
lovell commentedon Jul 29, 2026
Hello, I tried this locally (Linux x64, Node.js 24.18.0) with the sample font and get what I think is the expected output:
Please can you try adding the
NODE_DEBUG=sharpenvironment variable to see if there are any other warnings during font loading.delucis commentedon Jul 29, 2026
NODE_DEBUG=sharpis moderately helpful in that it at least logs a warning if thefontfilepath is inaccurate (SHARP 44421: unable to load fontfile), but even with the path correct, I still can’t get it to use the font for some reason 🤔I was running inside an Astro file, so tried a plain old .js file I ran with
node, but same result.Here’s the full script I ran (basically the same as yours with a different
fontfilepath:And the output file it produced:
kleisauke commentedon Jul 30, 2026
Pango defaults to the CoreText rendering and mapping backend on macOS. You could try to use the Fontconfig backend with the
PANGOCAIRO_BACKEND="fontconfig"environment variable. See: #2399.lovell commentedon Jul 30, 2026
Thanks for checking, are you able to reproduce on any platform other than Intel-based macOS? Perhaps something is going wrong creating the prebuilt binaries? I took a look at the build logs and there is a compiler warning on macOS:
It's also worth explicitly setting the
PANGOCAIRO_BACKEND=fontconfigenvironment variable in case something else is overriding it - see https://sharp.pixelplumbing.com/install/#fontsUPDATE: I hadn't see Kleis' comment when posting this (thanks to GitHub's annoyingly-laggy UI), so yes,
PANGOCAIRO_BACKENDis probably your friend here.delucis commentedon Jul 30, 2026
Thanks for the help both!
I can confirm that running the script with
PANGOCAIRO_BACKEND="fontconfig"produces the expected output on the Intel macOS.I just tried on an M2 Mac and found new issues! 😄
(Edit: just clicked that the script hanging was on me for not catching the async error when
await-ing the call to sharp)This comment helped me though: #4208 (comment)
I created an empty
font.confnext to the script:I updated the script based on Using custom fonts from a ttf file #4208 (comment) to set the
FONTCONFIG_FILEvariable and runningfc-cachebeforesharp()runs. (The path needs to be an absolute path from my tests, hence resolving it rather than just using the relative./fonts.confpath.)I did still have to run with
PANGOCAIRO_BACKEND="fontconfig"to get the expected output.I guess it’s hard to know if that stuff is needed when building in a repo that needs to run in various environments (e.g. different dev machines + CI)? I’m not sure how I’d check if
fonts.confis missing and only do this when required.Edit: I’m not 100% sure if the
fc-cachestep is needed. I tried running it in the terminal to reset it and then commented it out in the script. The script still produced the correct output. Not sure if that’s a) because the previous run of the script changed some state that persisted or b) because that step is not actually needed.lovell commentedon Jul 30, 2026
Does running
brew install fontconfigon the ARM-based macOS also "fix" this, or at least provide enough basic plumbing for fontconfig? IIRC runningfc-cachedoes things like scan for system fonts so probably isn't required when an explicit path to a font file is provided.We can probably improve sharp a bit here by emiting a warning on macOS when using
fontfilebutPANGOCAIRO_BACKENDis unset.delucis commentedon Jul 31, 2026
Didn’t change anything for me, no. The basic script still errors with “Fontconfig error: Cannot load default config file: File not found” even after running
brew install fontconfigand restarting the terminal session for good measure.lovell commentedon Aug 2, 2026
I've opened a PR for a possible improvement to libvips around
fontfileerror/warning handling - see libvips/libvips#5162