{"record":{"id":"3e04bd3c79e5bc35","repo":"pola-rs/polars","slug":"categorical-physical-must-be-one-of-pl-uint-8-16-3","errorCode":null,"errorMessage":"Categorical physical must be one of pl.UInt(8|16|32)","messagePattern":"Categorical physical must be one of pl\\.UInt\\(8\\|16\\|32\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/datatypes/classes.py","lineNumber":778,"sourceCode":"        physical: PolarsDataType = pldt.UInt32,\n    ) -> None:\n        if name is None or name == \"\":\n            assert namespace == \"\", \"global categories may not specify a namespace\"\n            assert physical == pldt.UInt32, (\n                \"global categories may not specify a physical type\"\n            )\n            self._categories = PyCategories.global_categories()\n            return\n\n        if physical == pldt.UInt32:\n            internal_phys = \"u32\"\n        elif physical == pldt.UInt16:\n            internal_phys = \"u16\"\n        elif physical == pldt.UInt8:\n            internal_phys = \"u8\"\n        else:\n            msg = \"Categorical physical must be one of pl.UInt(8|16|32)\"\n            raise TypeError(msg)\n\n        self._categories = PyCategories(name, namespace, internal_phys)\n\n    @staticmethod\n    def _from_py_categories(py_categories: PyCategories) -> Categories:\n        self = Categories.__new__(Categories)\n        self._categories = py_categories\n        return self\n\n    @staticmethod\n    def random(\n        namespace: str = \"\", physical: PolarsDataType = pldt.UInt32\n    ) -> Categories:\n        \"\"\"\n        Creates a new `Categories` with a random name.\n\n        Parameters\n        ----------","sourceCodeStart":760,"sourceCodeEnd":796,"githubUrl":"https://github.com/pola-rs/polars/blob/fe841f959ef4d2ceefc05a310d33ed7b1ab24e5e/py-polars/src/polars/datatypes/classes.py#L760-L796","documentation":"The `Categories` class stores categorical data with a fixed physical representation that must be one of the Polars unsigned integer types UInt8, UInt16, or UInt32. Any other physical dtype passed to the constructor raises this TypeError.","triggerScenarios":"`pl.Categories(physical=pl.Int32)` or passing a string, `pl.Categorical`, or signed integer dtype as `physical`.","commonSituations":"Developers assume any integer dtype works as physical backing, or pass the dtype name as a string instead of the class.","solutions":["Pass exactly `pl.UInt8`, `pl.UInt16`, or `pl.UInt32` as `physical`","Choose the width by category count: UInt8 for <=255, UInt16 for <=65535, otherwise UInt32","Do not pass dtype names as strings; import and pass the classes"],"exampleFix":"// before\npl.Categories(physical=pl.Int32)\n// after\npl.Categories(physical=pl.UInt32)","handlingStrategy":"validation","validationCode":"import polars as pl\nALLOWED_PHYSICAL = (pl.UInt8, pl.UInt16, pl.UInt32)\nif physical not in ALLOWED_PHYSICAL:\n    raise TypeError(f'physical must be one of {ALLOWED_PHYSICAL}')","typeGuard":"def is_valid_physical(p) -> bool:\n    import polars as pl\n    return p in (pl.UInt8, pl.UInt16, pl.UInt32)","tryCatchPattern":"try:\n    cats = pl.Categories(physical=physical)\nexcept TypeError as e:\n    if 'Categorical physical' in str(e):\n        cats = pl.Categories(physical=pl.UInt32)\n    else:\n        raise","preventionTips":["Only pass pl.UInt8/UInt16/UInt32 as categorical physical dtype","Pick width based on expected cardinality (255/65535 limits)"],"tags":["polars","categorical","datatypes","validation"],"backgroundTag":"invalid-enum-value","analyzedSha":"fe841f959ef4d2ceefc05a310d33ed7b1ab24e5e","analyzedAt":"2026-09-18T22:14:11.667Z","contentChangedAt":"2026-09-18T22:14:11.667Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}