Summary
forecast() on a reconciled mable crashes with a segmentation fault (Windows exit code -1073741819 / 0xC0000005, equivalent to Unix signal 139) when the tsibble was constructed using manual key columns. The identical data and models work correctly when the hierarchy is defined via aggregate_key().
The crash is in native code and cannot be caught by tryCatch(). It kills the R process immediately.
Environment
R 4.5.2 (2025-10-31 ucrt), x86_64-w64-mingw32
Windows 11 x64 (build 26200)
fable 0.5.0
fabletools 0.6.1
distributional 0.7.0
tsibble 1.2.0
LAPACK version 3.12.1
Matrix products: default
R version 4.5.2 (2025-10-31 ucrt)
Platform: x86_64-w64-mingw32/x64
Running under: Windows 11 x64 (build 26200)
Matrix products: default
LAPACK version 3.12.1
locale:
[1] LC_COLLATE=English_United States.utf8
[2] LC_CTYPE=English_United States.utf8
[3] LC_MONETARY=English_United States.utf8
[4] LC_NUMERIC=C
[5] LC_TIME=English_United States.utf8
time zone: America/New_York
tzcode source: internal
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] distributional_0.7.0 tsibble_1.2.0 fable_0.5.0
[4] fabletools_0.6.1
loaded via a namespace (and not attached):
[1] vctrs_0.7.1 cli_3.6.5 rlang_1.1.7 purrr_1.2.1
Minimum Reproducible Example:
library(fable)
library(tsibble)
library(dplyr)
set.seed(42)
n <- 50
base <- tibble(
index = rep(1:n, 2),
key = rep(c("A", "B"), each = n),
value = rnorm(n * 2, 100, 20)
) %>% as_tsibble(index = index, key = key)
--- This WORKS ---
agg <- base %>% aggregate_key(key, value = sum(value))
fit1 <- agg %>% model(m = ARIMA(value))
rec1 <- fit1 %>% reconcile(m = min_trace(m, method = "wls_var"))
fc1 <- rec1 %>% forecast(h = 3)
cat("aggregate_key: OK,", nrow(fc1), "rows\n")
--- This SEGFAULTS ---
Note: manual approach has only bottom-level series (no aggregate total row).
reconcile() accepts this without error, but forecast() segfaults.
manual <- base %>%
as_tibble() %>%
mutate(parent = "All") %>%
as_tsibble(index = index, key = c(parent, key))
fit2 <- manual %>% model(m = ARIMA(value))
rec2 <- fit2 %>% reconcile(m = min_trace(m, method = "wls_var"))
fc2 <- rec2 %>% forecast(h = 3) # <-- crashes here
[5] generics_0.1.4 S7_0.2.1 glue_1.8.0 anytime_0.3.12
[9] scales_1.4.0 grid_4.5.2 tibble_3.3.1 lifecycle_1.0.5
[13] ggtime_0.2.0 compiler_4.5.2 dplyr_1.2.0 RColorBrewer_1.1-3
[17] Rcpp_1.1.1 timechange_0.4.0 pkgconfig_2.0.3 tidyr_1.3.2
[21] farver_2.1.2 R6_2.6.1 tidyselect_1.2.1 pillar_1.11.1
[25] magrittr_2.0.4 tools_4.5.2 gtable_0.3.6 lubridate_1.9.5
[29] ggplot2_4.0.2
Additional observations
The segfault occurs even with the simplest case: 2 bottom-level series and 1 parent key.
Replacing NA with empty strings in key columns does not help.
Tested with flat hierarchies using aggregate_key() up to 45 series (tourism dataset, State * Purpose), all pass.
The issue is not related to data size or hierarchy depth, only to how the keys are defined.
Wrapping manual key columns in fabletools::agg_vec() alone does not prevent the crash. However, manually constructing a tsibble with agg_vec typed columns AND proper aggregate (total) rows (mirroring what aggregate_key() produces) does work. This suggests reconcile() + forecast() requires both agg_vec typed keys and the aggregate rows to construct a valid summing matrix, and segfaults instead of erroring when these are absent.
Context
Our production enrollment forecasting system uses a 7-level funnel hierarchy (Prospects > Started > Submitted > Completed > Admitted > Deposited > Enrolled) defined as manual key columns with a left_join().
This system originally used the hts package. When hts was deprecated (~2024), we migrated to fable/fabletools, keeping the manual key column approach. The fable-based code, including reconciliation with manual keys, was producing correct forecasts through October 2025 on the previous machine (R 4.4.x).
In early March 2026, we set up a new machine with fresh installs of R 4.5.2, RStudio, and all packages at their current CRAN versions. The segfault appeared on this new environment. We have not been able to determine whether the regression is in R 4.5.2, fabletools 0.6.1, or another dependency, since the old machine is no longer available for comparison.
Possible root cause
The forecast.lst_mint_mdl method calls build_key_data_smat() to construct the summing matrix used in reconciliation. This function relies on is_aggregated() to distinguish aggregate nodes from leaf nodes. When key columns are created via aggregate_key(), they are agg_vec typed and is_aggregated() works correctly. When key columns are plain character (as in the manual approach), is_aggregated() may return incorrect results, causing build_key_data_smat() to produce a malformed summing matrix. The segfault then occurs in native matrix operations when this matrix is applied during forecasting.
Regardless of whether manual key columns are officially supported for reconciliation, the crash should ideally be a clear R-level error rather than a process-killing segfault.
Workaround being explored
Restructuring data to use aggregate_key() or agg_vec() instead of plain character key columns. This is feasible because the funnel decomposition uses non-overlapping difference series that sum to their parents, but it requires a significant refactor.
Summary
forecast() on a reconciled mable crashes with a segmentation fault (Windows exit code -1073741819 / 0xC0000005, equivalent to Unix signal 139) when the tsibble was constructed using manual key columns. The identical data and models work correctly when the hierarchy is defined via aggregate_key().
The crash is in native code and cannot be caught by tryCatch(). It kills the R process immediately.
Environment
R 4.5.2 (2025-10-31 ucrt), x86_64-w64-mingw32
Windows 11 x64 (build 26200)
fable 0.5.0
fabletools 0.6.1
distributional 0.7.0
tsibble 1.2.0
LAPACK version 3.12.1
Matrix products: default
R version 4.5.2 (2025-10-31 ucrt)
Platform: x86_64-w64-mingw32/x64
Running under: Windows 11 x64 (build 26200)
Matrix products: default
LAPACK version 3.12.1
locale:
[1] LC_COLLATE=English_United States.utf8
[2] LC_CTYPE=English_United States.utf8
[3] LC_MONETARY=English_United States.utf8
[4] LC_NUMERIC=C
[5] LC_TIME=English_United States.utf8
time zone: America/New_York
tzcode source: internal
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] distributional_0.7.0 tsibble_1.2.0 fable_0.5.0
[4] fabletools_0.6.1
loaded via a namespace (and not attached):
[1] vctrs_0.7.1 cli_3.6.5 rlang_1.1.7 purrr_1.2.1
Minimum Reproducible Example:
library(fable)
library(tsibble)
library(dplyr)
set.seed(42)
n <- 50
base <- tibble(
index = rep(1:n, 2),
key = rep(c("A", "B"), each = n),
value = rnorm(n * 2, 100, 20)
) %>% as_tsibble(index = index, key = key)
--- This WORKS ---
agg <- base %>% aggregate_key(key, value = sum(value))
fit1 <- agg %>% model(m = ARIMA(value))
rec1 <- fit1 %>% reconcile(m = min_trace(m, method = "wls_var"))
fc1 <- rec1 %>% forecast(h = 3)
cat("aggregate_key: OK,", nrow(fc1), "rows\n")
--- This SEGFAULTS ---
Note: manual approach has only bottom-level series (no aggregate total row).
reconcile() accepts this without error, but forecast() segfaults.
manual <- base %>%
as_tibble() %>%
mutate(parent = "All") %>%
as_tsibble(index = index, key = c(parent, key))
fit2 <- manual %>% model(m = ARIMA(value))
rec2 <- fit2 %>% reconcile(m = min_trace(m, method = "wls_var"))
fc2 <- rec2 %>% forecast(h = 3) # <-- crashes here
[5] generics_0.1.4 S7_0.2.1 glue_1.8.0 anytime_0.3.12
[9] scales_1.4.0 grid_4.5.2 tibble_3.3.1 lifecycle_1.0.5
[13] ggtime_0.2.0 compiler_4.5.2 dplyr_1.2.0 RColorBrewer_1.1-3
[17] Rcpp_1.1.1 timechange_0.4.0 pkgconfig_2.0.3 tidyr_1.3.2
[21] farver_2.1.2 R6_2.6.1 tidyselect_1.2.1 pillar_1.11.1
[25] magrittr_2.0.4 tools_4.5.2 gtable_0.3.6 lubridate_1.9.5
[29] ggplot2_4.0.2
Additional observations
The segfault occurs even with the simplest case: 2 bottom-level series and 1 parent key.
Replacing NA with empty strings in key columns does not help.
Tested with flat hierarchies using aggregate_key() up to 45 series (tourism dataset, State * Purpose), all pass.
The issue is not related to data size or hierarchy depth, only to how the keys are defined.
Wrapping manual key columns in fabletools::agg_vec() alone does not prevent the crash. However, manually constructing a tsibble with agg_vec typed columns AND proper aggregate (total) rows (mirroring what aggregate_key() produces) does work. This suggests reconcile() + forecast() requires both agg_vec typed keys and the aggregate rows to construct a valid summing matrix, and segfaults instead of erroring when these are absent.
Context
Our production enrollment forecasting system uses a 7-level funnel hierarchy (Prospects > Started > Submitted > Completed > Admitted > Deposited > Enrolled) defined as manual key columns with a left_join().
This system originally used the hts package. When hts was deprecated (~2024), we migrated to fable/fabletools, keeping the manual key column approach. The fable-based code, including reconciliation with manual keys, was producing correct forecasts through October 2025 on the previous machine (R 4.4.x).
In early March 2026, we set up a new machine with fresh installs of R 4.5.2, RStudio, and all packages at their current CRAN versions. The segfault appeared on this new environment. We have not been able to determine whether the regression is in R 4.5.2, fabletools 0.6.1, or another dependency, since the old machine is no longer available for comparison.
Possible root cause
The forecast.lst_mint_mdl method calls build_key_data_smat() to construct the summing matrix used in reconciliation. This function relies on is_aggregated() to distinguish aggregate nodes from leaf nodes. When key columns are created via aggregate_key(), they are agg_vec typed and is_aggregated() works correctly. When key columns are plain character (as in the manual approach), is_aggregated() may return incorrect results, causing build_key_data_smat() to produce a malformed summing matrix. The segfault then occurs in native matrix operations when this matrix is applied during forecasting.
Regardless of whether manual key columns are officially supported for reconciliation, the crash should ideally be a clear R-level error rather than a process-killing segfault.
Workaround being explored
Restructuring data to use aggregate_key() or agg_vec() instead of plain character key columns. This is feasible because the funnel decomposition uses non-overlapping difference series that sum to their parents, but it requires a significant refactor.