pola-rs/polars · error · ValueError

`encoding` must be one of {'hex', 'base64'}, got {encoding!r

Error message

`encoding` must be one of {'hex', 'base64'}, got {encoding!r}

What it means

Raised by `Expr.str.decode(encoding, strict=...)` when `encoding` is neither 'hex' nor 'base64'. Despite the name, this method only reverses binary-to-text transfer encodings — it is not a general character-set decoder like Python's `bytes.decode`. The check is a plain Python if/elif that falls through to ValueError.

Source

Thrown at py-polars/src/polars/expr/string.py:1433

        >>> df.with_columns(pl.col("color").str.decode("hex").alias("decoded"))
        shape: (3, 2)
        ┌────────┬─────────────────┐
        │ color  ┆ decoded         │
        │ ---    ┆ ---             │
        │ str    ┆ binary          │
        ╞════════╪═════════════════╡
        │ 000000 ┆ b"\x00\x00\x00" │
        │ ffff00 ┆ b"\xff\xff\x00" │
        │ 0000ff ┆ b"\x00\x00\xff" │
        └────────┴─────────────────┘
        """
        if encoding == "hex":
            return wrap_expr(self._pyexpr.str_hex_decode(strict))
        elif encoding == "base64":
            return wrap_expr(self._pyexpr.str_base64_decode(strict))
        else:
            msg = f"`encoding` must be one of {{'hex', 'base64'}}, got {encoding!r}"
            raise ValueError(msg)

    def encode(self, encoding: TransferEncoding) -> Expr:
        """
        Encode values using the provided encoding.

        Parameters
        ----------
        encoding : {'hex', 'base64'}
            The encoding to use.

        .. engine-support:: in-memory, streaming, distributed

        Returns
        -------
        Expr
            Expression of data type :class:`String`.

        Examples

View on GitHub (pinned to 5d8ebabf11)

Solutions

  1. Use 'hex' or 'base64' — these are the only supported encodings.
  2. For character-set decoding of binary data, use `map_elements` with Python's codecs, accepting the performance cost.
  3. If the decoded bytes are UTF-8 text, chain with a cast: decode to Binary then `.cast(pl.String)` via `map_elements(bytes.decode, ...)`.
  4. Double-check case: 'Hex' with a capital H is rejected.

Example fix

# before
pl.col("s").str.decode("utf-8")

# after
pl.col("s").str.decode("base64")  # only 'hex' and 'base64' exist
Defensive patterns

Strategy: validation

Validate before calling

TRANSFER_ENCODINGS = {"hex", "base64"}
if encoding not in TRANSFER_ENCODINGS:
    raise ValueError(
        f"str.decode supports only {sorted(TRANSFER_ENCODINGS)}, got {encoding!r}; "
        "for charset decoding use map_elements with codecs"
    )
out = pl.col(c).str.decode(encoding, strict=strict)

Type guard

from typing import Literal, TypeGuard

TransferEncoding = Literal["hex", "base64"]

def is_transfer_encoding(x: object) -> TypeGuard[TransferEncoding]:
    return isinstance(x, str) and x in ("hex", "base64")

Prevention

When it happens

Trigger: `pl.col("s").str.decode("utf-8")`, `"ascii"`, `"latin-1"`, or a case variant like "Hex"; treating hex/base64-decoded output as text instead of `Binary` data.

Common situations: Developers assuming str.decode mirrors Python's codecs module; processing base64 blobs from APIs and reaching for the wrong encoding name; forgetting that the output is a Binary column that still needs further handling to become text.

Related errors


AI-assisted analysis of pola-rs/polars@5d8ebabf11 (2026-08-19). Data as JSON: /api/errors/3c1134d655637aad. Report an issue: GitHub.