grosser/parallel_tests · error · RuntimeError

Number of isolated processes must be >= total number of proc

Error message

Number of isolated processes must be >= total number of processes

What it means

In Grouper.in_even_groups_by_size, isolated processes (from --isolate-n, or one when --isolate is set) are carved off the front of the group list before the remaining files are distributed. If the isolate count reaches the total process count there is no group left for the non-isolated tests, so it raises. Note the message wording is inverted: the enforced rule is isolate count < total processes.

Source

Thrown at lib/parallel_tests/grouper.rb:30

        in_even_groups_by_size(scenarios, num_groups)
      end

      def in_even_groups_by_size(items, num_groups, options = {})
        groups = Array.new(num_groups) { { items: [], size: 0 } }

        return specify_groups(items, num_groups, options, groups) if options[:specify_groups]

        # add all files that should run in a single process to one group
        single_process_patterns = options[:single_process] || []

        single_items, items = items.partition do |item, _size|
          single_process_patterns.any? { |pattern| item =~ pattern }
        end

        isolate_count = isolate_count(options)

        if isolate_count >= num_groups
          raise 'Number of isolated processes must be >= total number of processes'
        end

        if isolate_count >= 1
          # add all files that should run in a multiple isolated processes to their own groups
          group_features_by_size(items_to_group(single_items), groups[0..(isolate_count - 1)])
          # group the non-isolated by size
          group_features_by_size(items_to_group(items), groups[isolate_count..])
        else
          # add all files that should run in a single non-isolated process to first group
          single_items.each { |item, size| add_to_group(groups.first, item, size) }

          # group all by size
          group_features_by_size(items_to_group(items), groups)
        end

        groups.map! { |g| g[:items].sort }
      end

View on GitHub (pinned to a06047856d)

Solutions

  1. Raise -n so it exceeds the isolate count (e.g. -n 3 with --isolate-n 2)
  2. Or lower --isolate-n, or drop --isolate entirely
  3. Never pair --isolate with -n 1 -- if you want one process without isolation semantics, use -n 0 / --non-parallel

Example fix

# before
parallel_test -n 2 --isolate-n 2

# after
parallel_test -n 3 --isolate-n 2
Defensive patterns

Strategy: validation

Validate before calling

# Validate your own config values before building the command
n = 3            # total processes (-n)
isolate_n = 2    # isolated processes (--isolate-n; --isolate counts as 1)
if isolate_n >= n
  abort "--isolate-n must stay below the total process count (-n): got #{isolate_n} >= #{n}"
end

Type guard

def isolation_config_valid?(total_processes, isolate_count)
  isolate_count < total_processes # enforced rule, despite the misleading error text
end

Try / catch

begin
  ParallelTests::Grouper.in_even_groups_by_size(items, n, isolate: isolate_n > 0, isolate_count: isolate_n)
rescue RuntimeError => e
  abort "#{e.message} -- keep --isolate-n strictly below -n"
end

Prevention

When it happens

Trigger: `parallel_test -n 1 --isolate`; `parallel_test -n 3 --isolate-n 3`; `--isolate-n 5` with `-n 4`; also when -n comes from the CPU-count default on a small CI runner, e.g. 2 vCPUs with --isolate-n 2.

Common situations: CI runners with fewer CPUs than the developer machine the flags were written on; lowering -n to save CI minutes without touching --isolate-n; pairing --isolate with a single-process run.

Related errors


AI-assisted analysis of grosser/parallel_tests@a06047856d (2026-08-23). Data as JSON: /api/errors/71dbe0271fa639a9. Report an issue: GitHub.