{"record":{"id":"71dbe0271fa639a9","repo":"grosser/parallel_tests","slug":"number-of-isolated-processes-must-be-total-numb","errorCode":null,"errorMessage":"Number of isolated processes must be >= total number of processes","messagePattern":"Number of isolated processes must be >= total number of processes","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"lib/parallel_tests/grouper.rb","lineNumber":30,"sourceCode":"        in_even_groups_by_size(scenarios, num_groups)\n      end\n\n      def in_even_groups_by_size(items, num_groups, options = {})\n        groups = Array.new(num_groups) { { items: [], size: 0 } }\n\n        return specify_groups(items, num_groups, options, groups) if options[:specify_groups]\n\n        # add all files that should run in a single process to one group\n        single_process_patterns = options[:single_process] || []\n\n        single_items, items = items.partition do |item, _size|\n          single_process_patterns.any? { |pattern| item =~ pattern }\n        end\n\n        isolate_count = isolate_count(options)\n\n        if isolate_count >= num_groups\n          raise 'Number of isolated processes must be >= total number of processes'\n        end\n\n        if isolate_count >= 1\n          # add all files that should run in a multiple isolated processes to their own groups\n          group_features_by_size(items_to_group(single_items), groups[0..(isolate_count - 1)])\n          # group the non-isolated by size\n          group_features_by_size(items_to_group(items), groups[isolate_count..])\n        else\n          # add all files that should run in a single non-isolated process to first group\n          single_items.each { |item, size| add_to_group(groups.first, item, size) }\n\n          # group all by size\n          group_features_by_size(items_to_group(items), groups)\n        end\n\n        groups.map! { |g| g[:items].sort }\n      end\n","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/grosser/parallel_tests/blob/a06047856d3564ee77848e230d61cb6503037ad7/lib/parallel_tests/grouper.rb#L12-L48","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","solutions":["Raise -n so it exceeds the isolate count (e.g. -n 3 with --isolate-n 2)","Or lower --isolate-n, or drop --isolate entirely","Never pair --isolate with -n 1 -- if you want one process without isolation semantics, use -n 0 / --non-parallel"],"exampleFix":"# before\nparallel_test -n 2 --isolate-n 2\n\n# after\nparallel_test -n 3 --isolate-n 2","handlingStrategy":"validation","validationCode":"# Validate your own config values before building the command\nn = 3            # total processes (-n)\nisolate_n = 2    # isolated processes (--isolate-n; --isolate counts as 1)\nif isolate_n >= n\n  abort \"--isolate-n must stay below the total process count (-n): got #{isolate_n} >= #{n}\"\nend","typeGuard":"def isolation_config_valid?(total_processes, isolate_count)\n  isolate_count < total_processes # enforced rule, despite the misleading error text\nend","tryCatchPattern":"begin\n  ParallelTests::Grouper.in_even_groups_by_size(items, n, isolate: isolate_n > 0, isolate_count: isolate_n)\nrescue RuntimeError => e\n  abort \"#{e.message} -- keep --isolate-n strictly below -n\"\nend","preventionTips":["Derive --isolate-n from the same variable as -n in CI templates (e.g. n = cpus, isolate_n = n / 2)","Add a preflight assertion in the CI script that fails fast when isolate_n >= n","Remember --isolate implies isolate-n 1, so it can never run with -n 1"],"tags":["ruby","parallel-tests","grouper","isolate","process-count","configuration"],"backgroundTag":"process-count-mismatch","analyzedSha":"a06047856d3564ee77848e230d61cb6503037ad7","analyzedAt":"2026-08-23T10:12:36.391Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}