{"record":{"id":"7ad583927afe07ec","repo":"huggingface/transformers","slug":"multiple-different-capturing-groups-found-in-targe","errorCode":null,"errorMessage":"Multiple different capturing groups found in target_patterns: {unique_capturing_groups}. All target patterns must use the same capturing group pattern.","messagePattern":"Multiple different capturing groups found in target_patterns: (.+?)\\. All target patterns must use the same capturing group pattern\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/transformers/core_model_loading.py","lineNumber":809,"sourceCode":"        self.base_model_prefix: str | None = None\n\n        # We need to process a few exceptions here when instantiating the reverse mapping (i.e. the targets become\n        # sources, and sources become targets). The issues lie in the sources usually, so here we need to check the\n        # targets for the reversed mapping\n\n        # Process target_patterns: detect capturing groups and replace with \\1\n        # Store the original capturing group patterns for reverse mapping\n        target_capturing_groups: list[str] = []\n        for i, pattern in enumerate(self.target_patterns):\n            self.target_patterns[i], captured_group = process_target_pattern(pattern)\n            if captured_group is not None:\n                target_capturing_groups.append(captured_group)\n\n        # Validate that we only have one unique capturing group pattern across all targets\n        # This ensures deterministic reverse mapping when sources have \\1 backreferences\n        unique_capturing_groups = set(target_capturing_groups)\n        if len(unique_capturing_groups) > 1:\n            raise ValueError(\n                f\"Multiple different capturing groups found in target_patterns: {unique_capturing_groups}. \"\n                f\"All target patterns must use the same capturing group pattern.\"\n            )\n        unique_capturing_group = unique_capturing_groups.pop() if unique_capturing_groups else None\n\n        # We also need to check capturing groups in the sources during reverse mapping (e.g. timm_wrapper, sam3)\n        for i, pattern in enumerate(self.source_patterns):\n            # Replace capturing groups\n            if r\"\\1\" in pattern:\n                if unique_capturing_group is None:\n                    raise ValueError(\n                        f\"Source pattern '{pattern}' contains \\\\1 backreference, but no capturing groups \"\n                        f\"found in target_patterns.\"\n                    )\n                # Use the unique capturing group from target_patterns for all sources\n                pattern = pattern.replace(r\"\\1\", unique_capturing_group, 1)\n            # Potentially process a bit more for consistency - only if they are consistent pairs, i.e. the length is the same\n            if len(self.source_patterns) == len(self.target_patterns):","sourceCodeStart":791,"sourceCodeEnd":827,"githubUrl":"https://github.com/huggingface/transformers/blob/a597f974857b3d92939971296bc0deb93d33d780/src/transformers/core_model_loading.py#L791-L827","documentation":"Raised in WeightTransform.__init__ (core_model_loading.py:809) while validating regex capturing groups. Target patterns may carry at most ONE distinct capturing-group pattern across the whole list (e.g. all targets use the same '(\\d+)' style group), because reverse mapping substitutes matched group content back into source patterns via a single \\1 backreference. If two target patterns use different capturing groups, the reverse mapping becomes ambiguous and init fails.","triggerScenarios":"Constructing a WeightTransform/WeightConverter where target_patterns = [r'layers.(\\d+).q_proj', r'model.layers.(\\d+.attn).k_proj'] — i.e. two different capturing-group shapes. Also triggered by patterns with multiple nested groups in different arrangements across targets.","commonSituations":"Hand-writing conversion recipes for multi-layer models; authors naturally write per-layer regexes and accidentally vary the group structure (e.g. one target captures the index, another captures 'index.attn'). Usually a recipe-authoring bug caught at import/init time.","solutions":["Make every target pattern use the IDENTICAL capturing group substring (same regex text inside the parentheses).","Replace extra variation with non-capturing groups (?:...) or plain literals.","If two genuinely different group structures are needed, split into two separate WeightTransform/WeightConverter instances."],"exampleFix":"# before\nWeightTransform(source_patterns=[r'blk.(\\d+).*'], target_patterns=[r'layers.(\\d+)', r'layers.attn.(\\d+.\\w+)'])\n\n# after: single shared capturing group shape\nWeightTransform(source_patterns=[r'blk.(\\d+).*'], target_patterns=[r'layers.\\1.q_proj', r'layers.\\1.k_proj'])","handlingStrategy":"validation","validationCode":"groups = {m.group(1) for p in target_patterns if (m := re.search(r'\\((?!\\?:)[^)]*\\)', p))}\nassert len(groups) <= 1, f'multiple distinct capturing groups: {groups} — unify them or split into two transforms'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use exactly one capturing-group spelling across all target patterns.","Use non-capturing groups (?:...) for anything that must not participate in backreference mapping.","Split heterogeneous renames into multiple WeightTransform instances."],"tags":["weight-conversion","regex","pattern-mismatch","programmer-error"],"backgroundTag":null,"analyzedSha":"a597f974857b3d92939971296bc0deb93d33d780","analyzedAt":"2026-08-14T18:24:08.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}