When I first set up R on a fresh Debian linux box, I thought everything would be smooth sailing. But the moment I tried to install tidyverse, I hit a wall.
install.packages("tidyverse")
Instead of installing cleanly, my terminal lit up with a long error log. The important parts looked like this:
Using PKG_LIBS=-lfreetype -lpng16 -ltiff -lz -ljpeg -lbz2
Configuration failed to find one of freetype2 libpng libtiff-4 libjpeg...
<stdin>:1:10: fatal error: ft2build.h: No such file or directory
compilation terminated.
ERROR: configuration failed for package ‘ragg’
ERROR: dependency ‘ragg’ is not available for package ‘tidyverse’
ERROR: dependency ‘xml2’ had non-zero exit status
At first, I thought maybe my R setup was broken. But digging into it, I realized the issue was not with R—it was with my system dependencies.
What the Error Actually
ft2build.h: No such file or directory
→ This means the compiler couldn’t find FreeType headers. On Debian, they live in/usr/include/freetype2/
.ragg
failed → Theragg
package is responsible for high-quality graphics output in R. It depends on FreeType, PNG, JPEG, TIFF, zlib, bzip2, and font libraries. Missing any of these breaks the installation.xml2
failed → This needs the development headers forlibxml2
(libxml2-dev
).
In short: I didn’t just need R. I needed linux dev packages (headers and build tools) so R could compile its dependencies.
The Fix Installing All Required System Libraries
Here’s what I ran on my Debian system:
sudo apt update
# Core build tools
sudo apt install -y build-essential r-base-dev pkg-config
# Graphics + text stack (needed by ragg and friends)
sudo apt install -y \
libfreetype6-dev libpng-dev libtiff5-dev libjpeg-dev zlib1g-dev libbz2-dev \
libharfbuzz-dev libfribidi-dev libfontconfig1-dev libcairo2-dev libpango1.0-dev
# Common tidyverse dependencies
sudo apt install -y \
libxml2-dev libcurl4-openssl-dev libssl-dev libicu-dev
After this, R finally had everything it needed to compile tidyverse packages.
Tip: If you’re on a minimal VM or Docker container, almost none of these will be installed by default.
Reinstalling Tidyverse
With dependencies installed, I went back to R:
options(Ncpus = parallel::detectCores()) # faster builds
install.packages(c("ragg", "xml2")) # build problem packages first
install.packages("tidyverse")
This time, no errors.
Practice Verifying My Setup
I didn’t stop at “it installs.” I wanted to be sure my graphics stack, XML parsing, and tidyverse pipeline actually worked.
Test ragg
+ ggplot2
library(ggplot2)
agg_png("test_plot.png", width = 800, height = 500, res = 144)
ggplot(mtcars, aes(wt, mpg, color = factor(cyl))) +
geom_point(size = 3) +
labs(title = "Hello, ragg! ✓", color = "Cylinders")
dev.off()
If test_plot.png
is crisp and colorful, then FreeType + PNG + Cairo stack is working.
Test xml2
library(xml2)
doc <- read_xml("<root><msg>hi</msg></root>")
xml_text(xml_find_first(doc, "//msg"))
# [1] "hi"
If you see "hi"
, then libxml2
headers are correctly in place.
Test tidyverse
with Penguins
install.packages("palmerpenguins")
library(tidyverse)
library(palmerpenguins)
penguins |>
drop_na(bill_length_mm, flipper_length_mm, species) |>
group_by(species) |>
summarise(
n = n(),
avg_bill = mean(bill_length_mm),
avg_flipper = mean(flipper_length_mm),
.groups = "drop"
) |>
arrange(desc(n))
This gave me a neat grouped summary of penguin species data.
Final Thoughts
What I learned from this whole experience is that R itself isn’t the problem when packages fail it’s the missing system libraries that R relies on to compile everything properly. On Debian, the winning combination was simple: build-essential
and r-base-dev
for compilers, pkg-config
for library discovery, image and font development libraries for ragg
, plus libxml2-dev
, libcurl4-openssl-dev
, and libssl-dev
for networking and parsing. Once I had those installed, tidyverse compiled without issues and my R setup was smooth again. So if you ever see that scary ft2build.h not found
error, don’t panic just install the missing dev packages, retry, and confirm with a few test scripts.