Skip to content

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

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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