Discovered during work on #1262, Stage 1 of the v1.0 compilation-state work tracked in #1258. I asked Claude to write up the report below. This is an edge case unlikely to be hit by real users, but opening in case we can clean it up easily as part of v1.0.
Describe the bug
stanc_options_to_args() (R/model.R) builds the STANCFLAGS value that $compile() hands to make with quote_values = TRUE, which wraps every value except name in single quotes by hand:
paste0("--", option_name, "=", "'", option_value, "'")
Make expands that value and the shell splits it, and hand-written single quotes survive neither step in general. A value holding a ' ends the quoting early, and a $ is expanded by Make before the shell sees it. #1230 was the same defect for include paths, and #1262 fixed it there with make_shell_quote(), which single-quotes a word only when the shell could interpret something in it and doubles $ for Make. The stanc_options values were left alone in #1262 because they are not a Stage 1 item.
To Reproduce
mod <- cmdstan_model(stan_file, compile = FALSE)
mod$compile(stanc_options = list("filename-in-msg" = "it's.stan"), force_recompile = TRUE)
The direct stanc calls receive --filename-in-msg=it's.stan and succeed; the make step receives --filename-in-msg='it's.stan', the shell reads 'it' then s.stan' with an unterminated quote, and stanc never runs with the intended value.
Expected behavior
The make step receives the value the direct calls receive. Drop quote_values from stanc_options_to_args() and run make_shell_quote() over the direct vector to produce the Make vector, the way $compile() already does for the flags read from make/local. The name carve-out likely disappears with it, since a plain identifier contains nothing make_shell_quote() quotes. One round-trip test in the #1230 pattern, with a value holding a space, a quote and a dollar sign, asserting the flag stanc prints in verbose output.
Additional context
Not a regression. Same class as #820, #1227, #1230 and #1232. Found in the Codex review of #1262 (2026-09-09), which confirmed the branch did not make it worse.
Discovered during work on #1262, Stage 1 of the v1.0 compilation-state work tracked in #1258. I asked Claude to write up the report below. This is an edge case unlikely to be hit by real users, but opening in case we can clean it up easily as part of v1.0.
Describe the bug
stanc_options_to_args()(R/model.R) builds theSTANCFLAGSvalue that$compile()hands tomakewithquote_values = TRUE, which wraps every value exceptnamein single quotes by hand:Make expands that value and the shell splits it, and hand-written single quotes survive neither step in general. A value holding a
'ends the quoting early, and a$is expanded by Make before the shell sees it. #1230 was the same defect for include paths, and #1262 fixed it there withmake_shell_quote(), which single-quotes a word only when the shell could interpret something in it and doubles$for Make. Thestanc_optionsvalues were left alone in #1262 because they are not a Stage 1 item.To Reproduce
The direct
stanccalls receive--filename-in-msg=it's.stanand succeed; themakestep receives--filename-in-msg='it's.stan', the shell reads'it'thens.stan'with an unterminated quote, andstancnever runs with the intended value.Expected behavior
The
makestep receives the value the direct calls receive. Dropquote_valuesfromstanc_options_to_args()and runmake_shell_quote()over the direct vector to produce the Make vector, the way$compile()already does for the flags read frommake/local. Thenamecarve-out likely disappears with it, since a plain identifier contains nothingmake_shell_quote()quotes. One round-trip test in the #1230 pattern, with a value holding a space, a quote and a dollar sign, asserting the flagstancprints in verbose output.Additional context
Not a regression. Same class as #820, #1227, #1230 and #1232. Found in the Codex review of #1262 (2026-09-09), which confirmed the branch did not make it worse.