Repository navigation
Pathfinder inits fail with "Assertion on 'weights' failed: Element <i> is not >= 0" #1323
Description
@jgabry, I'd like your opinion on what cmdstanr should do here
Problem
$sample(init = pathfinder_fit) can fail with:
Assertion on 'weights' failed: Element 163 is not >= 0.
The error comes from posterior::resample_draws() in process_init_approx(). This happened in a cluster run that used Pathfinder inits with num_paths = 10, single_path_draws = 40, draws = 4, psis_resample = FALSE. The Pathfinder seed was fixed, so the failure was deterministic, and a retry gave the same error. Versions: cmdstanr 0.9.0.9000, posterior 1.7.0. The code path is the same in current master (55342f4).
Cause
process_init_approx() (https://github.com/stan-dev/cmdstanr/blob/55342f4f6c/R/args.R#L1381-L1384) smooths the importance weights on the natural scale:
weights <- posterior::pareto_smooth(
exp(log_weights - max(log_weights)), tail = "right", r_eff=1, return_k=FALSE)When most Pathfinder paths are poor, lp__ - lp_approx__ is more than about 745 below the maximum for most draws. exp() of these values underflows to exactly 0, but the log weights stay distinct, so the smoothing branch is used. When more than ndraws - ndraws_tail weights are 0, the tail cutoff is 0 and ties with tail values. posterior::ps_tail() then moves the GPD location to 0 - .Machine$double.eps, and some smoothed weights are about -2e-16. resample_draws() rejects them.
Minimal example without Stan:
library(posterior)
w <- c(rep(0, 350), exp(-seq(0, 60, length.out = 50)))
ws <- pareto_smooth(w, tail = "right", r_eff = 1, return_k = FALSE, verbose = FALSE)
sum(ws < 0) # 7 with posterior 1.7.1
x <- as_draws_df(data.frame(theta = seq_along(ws)))
resample_draws(x, ndraws = 4, weights = ws, method = "simple_no_replace")
#> Error: Assertion on 'weights' failed: Element 341 is not >= 0.stan-dev/posterior#468 fixes the cause in ps_tail(): it removes the eps offset, so the smoothed tail cannot go below the cutoff. With that fix, the example gives no negative weights, and the natural-scale smoothing gives the same result as the log-scale smoothing (option 2 below).
Options for cmdstanr
cmdstanr requires posterior (>= 1.5.0), so users with an older posterior still get the error after the posterior fix. Possible changes:
-
Clamp after smoothing (one line):
weights <- pmax(weights, 0)
This works with every posterior version and adds no warning. The
rowsum()collapse that follows then sums non-negative values. -
Smooth on the log scale, which is the posterior API for importance weights:
weights <- exp(posterior::pareto_smooth( log_weights - max(log_weights), are_log_weights = TRUE, r_eff = 1, return_k = FALSE))
This does not have the defect in any posterior version, because
exp()of the result is never negative. Butlog_weightscan contain-Inf(L1370). For input with-Inf,pareto_smooth()does not smooth and gives the warning "Input contains infinite or NA values ...". To prevent the new warning, cmdstanr would have to smooth only the finite entries. -
No change in cmdstanr. Require the posterior version that contains the fix, after it is released.
I guess my preference is option 1, because it is the smallest change and it protects users with any posterior version. Which option do you prefer?
Activity
jgabry commentedon Oct 13, 2026
The clamp removes the negative weights but keeps the fit the eps offset distorted, so anyone with a current release of posterior would still resample from the wrong smoothed weights, right?
Unrelated, but can you update to the v1.0 branch (which has version number 0.99.0 for the release candidate. It's ready and I plan to announce this week.)? It would be good to get more use of that branch.
jgabry commentedon Oct 13, 2026
If you think that's not a problem then I'm ok with option 1.
That said, I was already thinking that we should increase the required posterior version when a new posterior release comes out because this recent PR (stan-dev/posterior#467) actually makes a big difference for cmdstanr users because of how cmdstanr uses those functions when reading draws from CSV.
avehtari commentedon Oct 13, 2026
If the required posterior version does include stan-dev/posterior#468, and v1.0 is released this week, then I think we don't need to do anything else
jgabry commentedon Oct 13, 2026
I'll be doing a CmdStanR 1.0 release candidate this week but not the actual release until more people have tested the release candidate (so maybe another week or a couple of weeks). The thing about posterior is that I don't know when Paul is planning to release next, so I'm not sure how long it will be until we can increase the required posterior version number to include your PR that's open and mine that was merged recently.
jgabry commentedon Oct 13, 2026
In other words, increasing the posterior version requirement won't be part of CmdStanR 1.0 unless there's a posterior release before the 1.0 release. But whenever the posterior release comes we can require it and do CmdStan 1.1 quickly with the new requirement.
jgabry commentedon Oct 14, 2026
Closing as fixed in #1324 and now available on the v1.0 branch