{"record":{"id":"eeadce44158ec8a0","repo":"pola-rs/polars","slug":"prefix-must-be-a-string-found-qualified-type-n","errorCode":null,"errorMessage":"'prefix' must be a string; found {qualified_type_name(prefix)!r}","messagePattern":"'prefix' must be a string; found (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/expr/categorical.py","lineNumber":176,"sourceCode":"        │ mango  ┆ false      │\n        │ null   ┆ null       │\n        └────────┴────────────┘\n\n        Using `starts_with` as a filter condition:\n\n        >>> df.filter(pl.col(\"fruits\").cat.starts_with(\"app\"))\n        shape: (1, 1)\n        ┌────────┐\n        │ fruits │\n        │ ---    │\n        │ cat    │\n        ╞════════╡\n        │ apple  │\n        └────────┘\n        \"\"\"\n        if not isinstance(prefix, str):\n            msg = f\"'prefix' must be a string; found {qualified_type_name(prefix)!r}\"\n            raise TypeError(msg)\n        return wrap_expr(self._pyexpr.cat_starts_with(prefix))\n\n    def ends_with(self, suffix: str) -> Expr:\n        \"\"\"\n        Check if string representations of values end with a substring.\n\n        .. engine-support:: in-memory, streaming, distributed\n\n        Parameters\n        ----------\n        suffix\n            Suffix substring.\n\n        See Also\n        --------\n        contains : Check if string reprs contains a substring that matches a pattern.\n        starts_with : Check if string reprs start with a substring.\n","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/pola-rs/polars/blob/fe841f959ef4d2ceefc05a310d33ed7b1ab24e5e/py-polars/src/polars/expr/categorical.py#L158-L194","documentation":"Type guard in Expr.cat.starts_with: the prefix argument must be a plain str; passing an Expr, Series, bytes, or other non-string type raises TypeError after inspecting the value's qualified type name.","triggerScenarios":"Calling pl.col('c').cat.starts_with(123), starts_with(b'app'), starts_with(None), or passing a variable holding an int/bytes instead of a string.","commonSituations":"Passing numeric prefixes read from config; passing bytes from network/file input without decoding; forgetting f-string/str() conversion when building the prefix dynamically.","solutions":["Convert the argument with str(prefix) before the call","Decode bytes: prefix.decode('utf-8')","Validate isinstance(prefix, str) before calling","Check that the right variable is passed (prefix vs its length or id)"],"exampleFix":"// before\ncat_col.cat.starts_with(b'app')\n// after\ncat_col.cat.starts_with('app')","handlingStrategy":"type-guard","validationCode":"if not isinstance(prefix, str):\n    raise TypeError(f'prefix must be str, got {type(prefix).__name__}')","typeGuard":"def is_str(x) -> bool:\n    return isinstance(x, str)","tryCatchPattern":"try:\n    e = col.cat.starts_with(prefix)\nexcept TypeError as e:\n    if 'must be a string' in str(e):\n        e = col.cat.starts_with(prefix.decode() if isinstance(prefix, bytes) else str(prefix))\n    else:\n        raise","preventionTips":["Decode bytes inputs before building expressions","str() any numeric/enum config values used as prefixes","Type-hint prefix as str and enable strict type checking"],"tags":["python","polars","type-error","categorical","strings"],"backgroundTag":"invalid-argument-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"}