Fix geom_spatvector Error: Problem While Converting Geom to Grob (!anyNA(x) is not TRUE)
When working with spatial data in R, integrating terra with ggplot2 via the excellent tidyterra extension is usually seamless. However, you might encounter a frustrating error when attempting to render certain GeoPackage (.gpkg) datasets using geom_spatvector():
Error in ggplot2::geom_sf():
! Problem while converting geom to grob.
ℹ Error occurred in the 1st layer.
Caused by error in FUN():
! !anyNA(x) is not TRUE
If you can plot the same file without issues using base sf::plot(st_geometry(x)), the problem often lies beneath the surface in empty geometries, M/Z dimensions, or missing coordinates that grid/ggplot2 graphical objects (grobs) cannot process. In this guide, we'll break down why this happens and explore the fastest ways to fix it.
What Causes the "!anyNA(x) is not TRUE" Grob Error?
Behind the scenes, tidyterra::geom_spatvector() converts the SpatVector object into an sf geometry collection before feeding it to ggplot2::geom_sf(), which then constructs grid graphical objects (grobs).
The specific failure !anyNA(x) is not TRUE occurs inside the grid conversion pipeline. Common culprits include:
- Empty Geometries: Some records in administrative boundaries (e.g., historical records, enclaves, or unassigned commune IDs) might have
GEOMETRYEMPTYrepresentations. - Z/M Coordinate Dimensions: Multi-dimensional coordinate arrays with missing Z (elevation) or M (measure) values trigger NA checks inside grid grob rendering.
- Invalid or Corrupted Geometry Rings: Geometries containing duplicate vertices or unclosed linear rings that fail coordinate extraction.
How to Fix It
1. Drop Empty and Null Geometries
The most frequent cause is the presence of empty geometries. You can filter out empty features directly in terra before passing the object to ggplot():
library(terra)
library(tidyterra)
library(ggplot2)
# Read the GeoPackage vector
v <- terra::vect(gpkg)
# Remove empty geometries
v_clean <- v[!is.empty(v), ]
# Plot again
ggplot(v_clean) +
geom_spatvector()
2. Drop Z/M Dimensions
If your GeoPackage contains 3D (XYZ) or measured (XYM) geometries where third-dimension values are undefined (or all NA), ggplot2 will throw an error when casting them to 2D screen coordinates. Strip extra dimensions down to 2D (XY):
# Check if the geometry has a Z coordinate
has_z <- terra::has.z(v)
# Alternatively, force conversion to 2D using sf
library(sf)
v_sf <- sf::st_read(gpkg, quiet = TRUE)
v_sf_2d <- sf::st_zm(v_sf, drop = TRUE, what = "ZM")
# Remove any empty geometries in sf
v_sf_clean <- v_sf_2d[!sf::st_is_empty(v_sf_2d), ]
# Plot directly with geom_sf
ggplot(v_sf_clean) +
geom_sf()
If you prefer to stay in the terra ecosystem, convert the cleaned sf object back into a SpatVector:
v_clean <- terra::vect(v_sf_clean)
ggplot(v_clean) +
geom_spatvector()
3. Repair Invalid Geometries
Self-intersecting rings or topology anomalies in high-resolution spatial boundaries can lead to NA vertices during polygon decomposition. You can quickly repair them using terra::makeValid():
# Repair geometries and remove empty ones
v_valid <- terra::makeValid(v)
v_clean <- v_valid[!is.empty(v_valid), ]
ggplot(v_clean) +
geom_spatvector()
Summary
When geom_spatvector() produces !anyNA(x) is not TRUE while converting to grobs, it almost always points to geometry features that grid cannot turn into polygons. By removing empty features with !is.empty(v), dropping extra dimensions with sf::st_zm(), and validating topology with terra::makeValid(), your maps will render smoothly in ggplot2.