{"record":{"id":"5596348c7bb9934f","repo":"pola-rs/polars","slug":"pad-start-expects-a-str-given-a-qualified-ty","errorCode":null,"errorMessage":"\"pad_start\" expects a `str`, given a {qualified_type_name(fill_char)!r}","messagePattern":"\"pad_start\" expects a `str`, given a (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/expr/string.py","lineNumber":899,"sourceCode":"        --------\n        >>> df = pl.DataFrame({\"a\": [\"cow\", \"monkey\", \"hippopotamus\", None]})\n        >>> df.with_columns(padded=pl.col(\"a\").str.pad_start(8, \"*\"))\n        shape: (4, 2)\n        ┌──────────────┬──────────────┐\n        │ a            ┆ padded       │\n        │ ---          ┆ ---          │\n        │ str          ┆ str          │\n        ╞══════════════╪══════════════╡\n        │ cow          ┆ *****cow     │\n        │ monkey       ┆ **monkey     │\n        │ hippopotamus ┆ hippopotamus │\n        │ null         ┆ null         │\n        └──────────────┴──────────────┘\n        \"\"\"\n        length_pyexpr = parse_into_expression(length)\n        if not isinstance(fill_char, str):\n            msg = f'\"pad_start\" expects a `str`, given a {qualified_type_name(fill_char)!r}'\n            raise TypeError(msg)\n        return wrap_expr(self._pyexpr.str_pad_start(length_pyexpr, fill_char))\n\n    def pad_end(self, length: int | IntoExprColumn, fill_char: str = \" \") -> Expr:\n        \"\"\"\n        Pad the end of the string until it reaches the given length.\n\n        .. engine-support:: in-memory, streaming, distributed\n\n        Parameters\n        ----------\n        length\n            Pad the string until it reaches this length. Strings with length equal to or\n            greater than this value are returned as-is. Can be int or expression.\n        fill_char\n            The character to pad the string with.\n\n        See Also\n        --------","sourceCodeStart":881,"sourceCodeEnd":917,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/expr/string.py#L881-L917","documentation":"Raised in the Python layer of Expr.str.pad_start before the call reaches the Rust engine: the fill_char argument must be a plain str. Any other type (int, bytes, None, an Expr) is rejected with a TypeError that names the qualified type of the offending value. The engine only accepts a string fill character, so this is a hard precondition on the argument, not a data-dependent runtime error.","triggerScenarios":"Calling pl.col('s').str.pad_start(10, fill_char=0), fill_char=None (e.g. an unset config value), fill_char=b'*' (bytes from a network/serialization layer), or passing a column expression as fill_char (only length is an IntoExpr; fill_char is a literal str parameter).","commonSituations":"Zero-padding IDs and passing the integer 0 instead of the string '0'; bytes values leaking in from JSON/binary protocols; an optional settings dict yielding None; assuming every string-namespace parameter accepts expressions.","solutions":["Pass fill_char as a str, e.g. fill_char='0' or fill_char='*'","If the value comes from config or data, convert before the call: str(value) or chr(code)","For zero-padding use .str.zfill(length), which takes no fill_char at all","A per-row fill character is unsupported; preprocess with map_batches if you truly need it"],"exampleFix":"# before\npl.col('id').str.pad_start(8, fill_char=0)\n\n# after\npl.col('id').str.pad_start(8, fill_char='0')\n# or, for zeros specifically:\npl.col('id').str.zfill(8)","handlingStrategy":"type-guard","validationCode":"fill_char = ' '\nassert isinstance(fill_char, str), 'fill_char must be str'\nexpr = pl.col('s').str.pad_start(10, fill_char=fill_char)","typeGuard":"def is_valid_fill_char(x: object) -> bool:\n    return isinstance(x, str) and len(x) >= 1","tryCatchPattern":null,"preventionTips":["Keep literal arguments (fill_char) and expression arguments (length) straight in the string namespace","Convert config values once at the boundary: str(value) or chr(code)","Use .str.zfill for zero padding so no fill_char is passed at all","Let a type checker (mypy/pyright) catch non-str fill_char via the annotated signature"],"tags":["polars","python","typeerror","string","argument-validation"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}