pola-rs/polars · error · TypeError
`Expr.str.json_decode` needs an explicitly given `dtype` oth
Error message
`Expr.str.json_decode` needs an explicitly given `dtype` otherwise Polars is not able to determine the output type. If you want to eagerly infer datatype you can use `Series.str.json_decode`.
What it means
Expr.str.json_decode executes lazily, so Polars must know the output schema when the query plan is built; the dtype argument is therefore mandatory and a TypeError is raised immediately when it is None. Eager schema inference only exists on the Series counterpart. The infer_schema_length parameter on the Expr version is deprecated and has no effect on execution.
Source
Thrown at py-polars/src/polars/expr/string.py:1351
>>> df = pl.DataFrame(
... {"json": ['{"a":1, "b": true}', None, '{"a":2, "b": false}']}
... )
>>> dtype = pl.Struct([pl.Field("a", pl.Int64), pl.Field("b", pl.Boolean)])
>>> df.with_columns(decoded=pl.col("json").str.json_decode(dtype))
shape: (3, 2)
┌─────────────────────┬───────────┐
│ json ┆ decoded │
│ --- ┆ --- │
│ str ┆ struct[2] │
╞═════════════════════╪═══════════╡
│ {"a":1, "b": true} ┆ {1,true} │
│ null ┆ null │
│ {"a":2, "b": false} ┆ {2,false} │
└─────────────────────┴───────────┘
"""
if dtype is None:
msg = "`Expr.str.json_decode` needs an explicitly given `dtype` otherwise Polars is not able to determine the output type. If you want to eagerly infer datatype you can use `Series.str.json_decode`."
raise TypeError(msg)
if infer_schema_length is not None:
issue_warning(
"`Expr.str.json_decode` with `infer_schema_length` is deprecated and has no effect on execution.",
DeprecationWarning,
)
dtype_expr = parse_into_datatype_expr(dtype)._pydatatype_expr
return wrap_expr(self._pyexpr.str_json_decode(dtype_expr))
def json_path_match(self, json_path: IntoExprColumn) -> Expr:
"""
Extract the first match from a JSON string using the provided JSONPath.
Throws errors if invalid JSON strings are encountered. All return values
are cast to :class:`String`, regardless of the original value.
Documentation on the JSONPath standard can be foundView on GitHub (pinned to df599052da)
Solutions
- Pass an explicit dtype: .str.json_decode(dtype=pl.Struct({'a': pl.Int64, 'b': pl.Bool}))
- If the schema is unknown, collect the column first and use the eager path: s = df['payload']; s.str.json_decode(infer_schema_length=100), then merge the result back
- Learn the schema once from a sample (df['payload'].head().str.json_decode(infer_schema_length=100).dtype) and hard-code it
- Drop infer_schema_length from the Expr call; it only emits a deprecation warning and changes nothing
Example fix
# before
pl.col('payload').str.json_decode()
# after
pl.col('payload').str.json_decode(
dtype=pl.Struct({'a': pl.Int64, 'b': pl.Bool})
)
# unknown schema: infer eagerly on a Series, then reuse
inferred = df['payload'].str.json_decode(infer_schema_length=100).dtype
df.select(pl.col('payload').str.json_decode(dtype=inferred)) Defensive patterns
Strategy: validation
Validate before calling
dtype = None # e.g. from caller config
if dtype is None:
# infer once, eagerly, then reuse
dtype = df['payload'].str.json_decode(infer_schema_length=100).dtype
out = df.select(pl.col('payload').str.json_decode(dtype=dtype)) Prevention
- Always pass an explicit dtype on the lazy/Expr path
- Reserve infer_schema_length for the Series (eager) API
- Cache the inferred schema once per JSON source instead of re-inferring
- Watch deprecation warnings — they flag paths that silently do nothing
When it happens
Trigger: df.select(pl.col('payload').str.json_decode()) with no dtype; porting Series.str.json_decode(s, infer_schema_length=100) code into an expression; a scan/pipe that assumed JSON schema auto-detection like pandas or pyarrow would do.
Common situations: JSON columns whose shape is only known at runtime; code migrated from eager notebooks (Series path worked) into lazy pipelines; older Polars versions or other libraries where inference was the default; users adding infer_schema_length to the Expr call and still hitting the error because it is ignored.
Related errors
- `schema_overrides` should be of type list or dict
- `schema_overrides` should be of type list or dict, got {qual
- There is no natural representation of DayTime in JSON.
- Deserialization from JSON not implemented for {adt:?}
- cannot select columns using key of type {qualified_type_name
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/2d6c9f19872e4782.
Report an issue: GitHub.