grosser/parallel_tests · error · RuntimeError
Can't pass --specify-groups with any of these keys: --single
Error message
Can't pass --specify-groups with any of these keys: --single, --isolate, or --isolate-n
What it means
--specify-groups pins exact specs to exact processes, while --single/-s, --isolate and --isolate-n also dictate which process certain tests land in. The two placement mechanisms would overwrite each other, so parse_options! rejects the combination by intersecting the options keys with [:single_process, :isolate, :isolate_count].
Source
Thrown at lib/parallel_tests/cli.rb:380
end
end
options[:files] = files.map { |file_path| Pathname.new(file_path).cleanpath.to_s }
end
append_test_options(options, remaining)
options[:group_by] ||= :filesize if options[:only_group]
if options[:group_by] == :found && options[:single_process]
raise "--group-by found and --single-process are not supported"
end
allowed = [:filesize, :runtime, :found]
if !allowed.include?(options[:group_by]) && options[:only_group]
raise "--group-by #{allowed.join(" or ")} is required for --only-group"
end
if options[:specify_groups] && options.keys.intersect?([:single_process, :isolate, :isolate_count])
raise "Can't pass --specify-groups with any of these keys: --single, --isolate, or --isolate-n"
end
if options[:failure_exit_code] && options[:highest_exit_status]
raise "Can't pass --failure-exit-code and --highest-exit-status"
end
options
end
def extract_file_paths(argv)
dash_index = argv.rindex("--")
file_args_at = (dash_index || -1) + 1
[argv[file_args_at..], argv[0...(dash_index || 0)]]
end
def extract_test_options(argv)
dash_index = argv.index("--") || -1
argv[dash_index + 1..]View on GitHub (pinned to a06047856d)
Solutions
- Remove --single/-s, --isolate and --isolate-n from the command
- If certain specs still must be isolated, express that inside --specify-groups by putting them alone in their own pipe-separated process group
Example fix
# before parallel_test -n 3 --isolate --specify-groups 'a_spec.rb|b_spec.rb' # after parallel_test -n 3 --specify-groups 'a_spec.rb|b_spec.rb'
Defensive patterns
Strategy: validation
Validate before calling
opts = ENV.fetch('PARALLEL_TEST_OPTS', '').shellsplit
conflicting = opts.any? { |o| o == '-s' || o.start_with?('--single', '--isolate') } # --isolate-n matches the --isolate prefix
if opts.include?('--specify-groups') && conflicting
abort 'parallel_tests: --specify-groups cannot be combined with --single/--isolate/--isolate-n'
end Type guard
def specify_groups_args_valid?(argv)
return true unless argv.any? { |a| a == '--specify-groups' || a.start_with?('--specify-groups=') }
argv.none? { |a| a == '-s' || a.start_with?('--single', '--isolate') }
end Try / catch
begin
ParallelTests::CLI.new.run(args)
rescue RuntimeError => e
abort "#{e.message} -- keep exactly one placement mechanism per command"
end Prevention
- Use one placement mechanism per command: manual pinning (--specify-groups) OR pattern-based isolation (--single/--isolate*)
- Review and prune old flags when adopting --specify-groups
- Keep CI job option strings per-job instead of sharing one global list
When it happens
Trigger: `parallel_test -n 3 --specify-groups 'a_spec.rb,b_spec.rb|c_spec.rb' --isolate`, the same with `-s pattern` or `--isolate-n 2`, or a rake/CI option string containing --specify-groups together with any isolation flag.
Common situations: Teams migrate from --isolate/--single workflows to explicit group pinning (e.g. to debug flaky splits) and forget to strip the old flags; shared CI option lists merge flags from several jobs into one string.
Related errors
- --group-by found and --single-process are not supported
- Both options are mutually exclusive: verbose & quiet
- --group-by #{allowed.join(" or ")} is required for --only-gr
- Can't pass --failure-exit-code and --highest-exit-status
- Number of processes separated by pipe must be less than or e
AI-assisted analysis of grosser/parallel_tests@a06047856d (2026-08-23).
Data as JSON: /api/errors/237a0c6453a08eff.
Report an issue: GitHub.