{"record":{"id":"efc09b94a61ce0dd","repo":"grosser/parallel_tests","slug":"number-of-processes-separated-by-pipe-must-be-less","errorCode":null,"errorMessage":"Number of processes separated by pipe must be less than or equal to the total number of processes","messagePattern":"Number of processes separated by pipe must be less than or equal to the total number of processes","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"lib/parallel_tests/grouper.rb","lineNumber":61,"sourceCode":"          group_features_by_size(items_to_group(items), groups)\n        end\n\n        groups.map! { |g| g[:items].sort }\n      end\n\n      private\n\n      def specified_groups(options)\n        groups = options[:specify_groups]\n        return groups if groups != '-'\n\n        $stdin.read.chomp\n      end\n\n      def specify_groups(items, num_groups, options, groups)\n        specify_test_process_groups = specified_groups(options).split('|')\n        if specify_test_process_groups.count > num_groups\n          raise 'Number of processes separated by pipe must be less than or equal to the total number of processes'\n        end\n\n        all_specified_tests = specify_test_process_groups.map { |group| group.split(',') }.flatten\n        specified_items_found, items = items.partition { |item, _size| all_specified_tests.include?(item) }\n\n        specified_specs_not_found = all_specified_tests - specified_items_found.map(&:first)\n        if specified_specs_not_found.any?\n          raise \"Could not find #{specified_specs_not_found} from --specify-groups in the selected files & folders\"\n        end\n\n        if specify_test_process_groups.count == num_groups && items.flatten.any?\n          raise(\n            <<~ERROR\n              The number of groups in --specify-groups matches the number of groups from -n but there were other specs\n              found in the selected files & folders not specified in --specify-groups. Make sure -n is larger than the\n              number of processes in --specify-groups if there are other specs that need to be run. The specs that aren't run:\n              #{items.map(&:first)}\n            ERROR","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/grosser/parallel_tests/blob/a06047856d3564ee77848e230d61cb6503037ad7/lib/parallel_tests/grouper.rb#L43-L79","documentation":"With --specify-groups, each pipe-separated segment claims one process out of the total (-n, defaulting to the CPU count, optionally multiplied). Grouper.specify_groups raises when the number of pipe segments exceeds the total because there are not enough processes to host them.","triggerScenarios":"`parallel_test --specify-groups '1_spec.rb|2_spec.rb|3_spec.rb'` on a 2-CPU machine (default -n 2); `parallel_test -n 2 --specify-groups 'a.rb|b.rb|c.rb'`; groups read from STDIN via `--specify-groups -` where the list has more pipes than -n.","commonSituations":"Hardcoded group lists in CI while the runner's CPU count differs from the author's machine; forgetting that -n defaults to the machine's processor count; appending a new group to the list without bumping -n.","solutions":["Set -n to at least the number of pipe-separated groups: `parallel_test -n 3 --specify-groups 'a.rb|b.rb|c.rb'`","Or merge groups with commas -- comma means same process, pipe means new process","When the list is dynamic (STDIN '-'), count the pipes and pass -n accordingly"],"exampleFix":"# before (2-CPU default)\nparallel_test --specify-groups '1_spec.rb|2_spec.rb|3_spec.rb'\n\n# after\nparallel_test -n 3 --specify-groups '1_spec.rb|2_spec.rb|3_spec.rb'","handlingStrategy":"validation","validationCode":"groups = 'a_spec.rb|b_spec.rb|c_spec.rb'\nn = 3\nif groups.split('|').count > n\n  abort \"--specify-groups defines #{groups.split('|').count} groups but only #{n} processes (-n)\"\nend","typeGuard":"def specify_groups_fit?(spec_string, num_processes)\n  spec_string.split('|').count <= num_processes\nend","tryCatchPattern":"begin\n  ParallelTests::CLI.new.run(args)\nrescue RuntimeError => e\n  abort \"#{e.message} -- raise -n to at least the number of pipe-separated groups\"\nend","preventionTips":["Compute -n from the group list in CI scripts instead of hardcoding both","Document comma-vs-pipe semantics (comma = same process, pipe = new process) next to the option","When reading groups from STDIN ('-'), count pipes first and pass a matching -n"],"tags":["ruby","parallel-tests","grouper","specify-groups","process-count"],"backgroundTag":"process-count-mismatch","analyzedSha":"a06047856d3564ee77848e230d61cb6503037ad7","analyzedAt":"2026-08-23T10:12:36.391Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}