Skip to content

build_aggregation_table() fails with terra >= 1.9.0: incorrect number of dimensions #3

@truenomad

Description

@truenomad

Hy Nat!

Just came across a new bug this morning. The build_aggregation_table() fails with terra >= 1.9.0 (released 2026-03-07) due to a change in how terra::extract() returns results. The error occurs in calculate_pixel_fractions_single_polygon() at the line extract_wide[1, ], which assumes a 2D object (data.frame/matrix), but terra 1.9.x returns a vector instead.

The mbg DESCRIPTION currently lists terra in Imports with no version constraint, so terra 1.9.1 installs without warning and silently breaks this function.

Error

Error in `extract_wide[1, ]`:
! incorrect number of dimensions

Traceback

 1. └─mbg::build_aggregation_table(...)
 2.   ├─data.table::rbindlist(...)
 3.   └─base::lapply(...)
 4.     └─mbg (local) FUN(X[[i]], ...)
 5.       └─mbg::calculate_pixel_fractions_single_polygon(...)
 6.         ├─data.table::data.table(...)
 7.         └─base::unlist(extract_wide[1, ])

Minimal Reproducible Example

library(terra)   # 1.9.1
library(mbg)
library(sf)

# Any valid admin shapefile + matching population raster
adm2_sf <- st_read("path/to/admin2.shp")
pop_rast <- rast("path/to/population.tif")

# Build ID raster
primary_vect <- terra::vect(adm2_sf)
primary_vect$poly_id <- seq_len(nrow(primary_vect))

id_raster <- mbg::build_id_raster(
  polygons = primary_vect,
  template_raster = pop_rast
)

# This fails with terra >= 1.9.0
mbg::build_aggregation_table(
  polygons = primary_vect,
  id_raster = id_raster,
  polygon_id_field = "poly_id",
  verbose = TRUE
)

Versions

  • terra: 1.9.1 (fails) / 1.8-93 (works)
  • mbg: 1.1.0
  • R: 4.x
  • OS: macOS

Root Cause

In calculate_pixel_fractions_single_polygon(), the line:

unlist(extract_wide[1, ])

assumes extract_wide is a data.frame or matrix. In terra >= 1.9.0, the underlying extract() call returns a different structure (vector) for single-polygon extractions, causing the [1, ] row subsetting to fail.

Suggested Fixes

Option A — Fix the code to handle both return types:

if (!is.data.frame(extract_wide)) {
  extract_wide <- as.data.frame(t(extract_wide))
}
unlist(extract_wide[1, ])

Option B — Pin terra in DESCRIPTION until the code is updated:

Imports:
    terra (< 1.9.0),
    ...

Workaround

My work around was to pin terra < 1.9.0 in my project (renv::install("terra@1.8-93")).

Happy to submit a PR if helpful.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions