You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This bug description was generated with the help of Claude. It's a real bug that Claude found although only max-line-length is a valid stanc option that could be affected by this, so relatively low priority.
Describe the bug
The loops that turn stanc_options into command-line arguments use isTRUE(as.logical(value)) to decide whether an option is a bare boolean flag:
if (isTRUE(as.logical(stanc_options[[i]]))) {
stanc_built_options <- c(stanc_built_options, paste0("--", option_name))
}
as.logical() is TRUE for any non-zero number, so a numeric value takes this branch and is discarded — only the option name is emitted. The valueless flag then swallows whatever argument follows it:
stanc: option --max-line-length needs an argument
$compile() and $check_syntax() are both affected. $format() has the same loop but already guards against it with && !is.numeric(stanc_options[[i]]).
To Reproduce
library(cmdstanr)
f <- tempfile(fileext = ".stan")
writeLines(c("parameters { real y; }", "model { y ~ std_normal(); }"), f)
numeric: fails
cmdstan_model(f, stanc_options = list("max-line-length" = 78))
#> stanc: option --max-line-length needs an argument
#> Error : ... failed to generate the model C++ header
Expected behavior
list("max-line-length" = 78) should produce --max-line-length=78, the same as the string form.
Additional context
--max-line-length is currently the only stanc option that takes a numeric value, so the practical impact today is small — but it's reachable, since stanc_options set on cmdstan_model() are stored and reused by $format(), which is where that option actually applies. Setting it up front breaks compilation. - The behavior is asymmetric in a confusing way: 0 works (as. falls through to the name=value branch) while any non-zeronumber does not.
Workaround: pass the value as a string.
The fix is to add && !is.numeric(stanc_options[[i]]) to the two loops that lack it, matching $format(). Longer term the three near-duplicate loops could be a single helper. Note that maintain separate direct and Make-quoted stanc options #1231 rewrites the $compile() loop, so that half may be easiest to fix there.
This bug description was generated with the help of Claude. It's a real bug that Claude found although only max-line-length is a valid stanc option that could be affected by this, so relatively low priority.
Describe the bug
The loops that turn stanc_options into command-line arguments use isTRUE(as.logical(value)) to decide whether an option is a bare boolean flag:
if (isTRUE(as.logical(stanc_options[[i]]))) {
stanc_built_options <- c(stanc_built_options, paste0("--", option_name))
}
as.logical() is TRUE for any non-zero number, so a numeric value takes this branch and is discarded — only the option name is emitted. The valueless flag then swallows whatever argument follows it:
stanc: option --max-line-length needs an argument
$compile() and $check_syntax() are both affected. $format() has the same loop but already guards against it with && !is.numeric(stanc_options[[i]]).
To Reproduce
library(cmdstanr)
f <- tempfile(fileext = ".stan")
writeLines(c("parameters { real y; }", "model { y ~ std_normal(); }"), f)
numeric: fails
cmdstan_model(f, stanc_options = list("max-line-length" = 78))
#> stanc: option --max-line-length needs an argument
#> Error : ... failed to generate the model C++ header
same value as a string: works
cmdstan_model(f, stanc_options = list("max-line-length" = "78
Expected behavior
list("max-line-length" = 78) should produce --max-line-length=78, the same as the string form.
Additional context