Skip to content

Quoted values in make/local STANCFLAGS are split on whitespace and break direct stanc calls #1232

Description

@jgabry

This bug description was generated with the help of Claude

Describe the bug

get_cmdstan_flags("STANCFLAGS") splits the flag string on whitespace (R/utils.R):

flags_vec <- strsplit(x = trimws(flags), split = "\s+", perl = TRUE)[[1]]

That splits inside a quoted value. A make/local containing

STANCFLAGS += --include-paths='/my dir'

becomes:

#> [1] "--include-paths='/my" "dir'"

compile() appends this vector to the stanc options and then uses it two ways:

  • for make, the elements are rejoined with spaces into STANCFLAGS += ..., which round-trips fine — the shell re-strips the quotes;
  • for the direct stanc calls in get_standalone_hpp() (which relements are passed to processx as separate arguments, so stanc receives --include-paths='/my and dir' as two distinct argv e

stanc then treats dir' as a positional argument:

stanc: too many arguments, don't know what to do with model.s

Only compile() is affected — $check_syntax() and $format() don't read local STANCFLAGS.

To Reproduce

Put a quoted, space-containing value in make/local:

STANCFLAGS += --include-paths='/my dir'

then compile any model. The equivalent failure can be seen directly:

stanc <- file.path(cmdstan_path(), "bin", "stanc")
processx::run(stanc, c("--include-paths='/my", "dir'", "model.stan"),
              error_on_status = FALSE)$stderr
#> stanc: too many arguments, don't know what to do with model.stan

Expected behavior

Flags read from make/local should reach direct stanc calls asould produce — i.e. --include-paths=/my dir as one argument, with the shell quoting removed rather than treated as part of

Additional context

Pre-existing, not a regression. This is the same class of bug as #820 and #1227 (shell quoting leaking into processx arguments), but for flags coming from make/local rather than from include_paths or stanc_options. #1231 splits the direct and make-quoted option vectors but keeps passing the split local flags to both, so it doesn't cover this case.

Not a duplicate of #1230, which is the mirror image: #1230 is about the quoting cmdstanr writes for Make in include_paths_stanc3_args() and explicitly does not affect direct stanc calls. This one is about the quoting cmdstanr reads from make/local in get_cmdstan_flags(), and affects only the direct calls. Neither fix resolves the other — flags from make/local never pass through include_paths_stanc3_args().

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions