{"record":{"id":"39a606025cc08c5c","repo":"pandas-dev/pandas","slug":"pat-must-contain-a-symbolic-group-name","errorCode":null,"errorMessage":"{pat=} must contain a symbolic group name.","messagePattern":"(.+?) must contain a symbolic group name\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/arrow/array.py","lineNumber":3697,"sourceCode":"        result = self._apply_elementwise(predicate)\n        return self._from_pyarrow_array(pa.chunked_array(result))\n\n    def _str_casefold(self) -> Self:\n        predicate = lambda val: val.casefold()\n        result = self._apply_elementwise(predicate)\n        return self._from_pyarrow_array(pa.chunked_array(result))\n\n    def _str_encode(self, encoding: str, errors: str = \"strict\") -> Self:\n        predicate = lambda val: val.encode(encoding, errors)\n        result = self._apply_elementwise(predicate)\n        return self._from_pyarrow_array(pa.chunked_array(result))\n\n    def _str_extract(self, pat: str, flags: int = 0, expand: bool = True):\n        if flags:\n            raise NotImplementedError(\"Only flags=0 is implemented.\")\n        groups = re.compile(pat).groupindex.keys()\n        if len(groups) == 0:\n            raise ValueError(f\"{pat=} must contain a symbolic group name.\")\n        result = pc.extract_regex(self._pa_array, pat)\n        if expand:\n            return {\n                col: self._from_pyarrow_array(pc.struct_field(result, [i]))\n                for col, i in zip(groups, range(result.type.num_fields), strict=True)\n            }\n        else:\n            return type(self)(pc.struct_field(result, [0]))\n\n    def _str_findall(self, pat: str, flags: int = 0) -> Self:\n        regex = re.compile(pat, flags=flags)\n        predicate = lambda val: regex.findall(val)\n        result = self._apply_elementwise(predicate)\n        return self._from_pyarrow_array(pa.chunked_array(result))\n\n    def _str_get_dummies(self, sep: str = \"|\", dtype: NpDtype | None = None):\n        if dtype is None:\n            dtype = np.bool_","sourceCodeStart":3679,"sourceCodeEnd":3715,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/arrow/array.py#L3679-L3715","documentation":"Raised by ArrowExtensionArray._str_extract when the supplied regex pattern contains no symbolic (named) group. The pyarrow path returns a struct whose fields are addressed positionally, but pandas' expand=True result is keyed by group names from `re.compile(pat).groupindex`, so at least one named group is mandatory. This is stricter than the object-dtype path, which accepts positional groups and synthesizes integer column names.","triggerScenarios":"Calling `ser.str.extract(r\"(\\d+)\")` (positional group only) on a pyarrow-backed string Series. The check `len(re.compile(pat).groupindex.keys()) == 0` fires whenever no `(?P<name>...)` group is present.","commonSituations":"Porting `str.extract` code that relied on integer-numbered capture groups from an object Series to a string[pyarrow] Series; patterns written for the numpy path.","solutions":["Add a symbolic group name to every capture group you want returned, e.g. `r\"(?P<num>\\d+)\"`.","If you cannot change the pattern, cast to object dtype (`ser.astype(object)`) before `.str.extract` to use the positional-group behavior."],"exampleFix":"# before\nser.str.extract(r\"(\\d+)-(\\d+)\")\n# after\nser.str.extract(r\"(?P<a>\\d+)-(?P<b>\\d+)\")","handlingStrategy":"validation","validationCode":"import re\ngroups = re.compile(pat).groupindex\nif not groups:\n    raise ValueError(f\"pattern {pat!r} needs at least one named group for arrow str.extract\")\nser.str.extract(pat)","typeGuard":"def has_named_group(pat: str) -> bool:\n    return len(re.compile(pat).groupindex) > 0","tryCatchPattern":"try:\n    out = ser.str.extract(pat)\nexcept ValueError as e:\n    if \"symbolic group name\" in str(e):\n        # add a default name and retry on object dtype\n        out = ser.astype(object).str.extract(pat)\n    else:\n        raise","preventionTips":["Always use (?P<name>...) named groups in str.extract patterns","Add a unit test asserting named groups when targeting pyarrow strings"],"tags":["pyarrow","string-accessor","regex","arrow-extension"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}