unstale

pypi / narwhals

narwhals

What changed in narwhals 2, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-30.

11 breaking4 new APIs and options2 performance2 behavior and defaults1 tooling37 fixes and other

See which of these apply to your code, ranked, in your agent:

npx @unstale/cli init

@unstale/cli on npm

narwhals 257 changes

Breaking changes 11

  • Returns null when no valid values exist.

    2.28.0release notes

  • Returns null when no valid values exist.

    2.28.0release notes

  • Mismatched items raise InvalidOperationError on pyarrow-backed backends.

    2.28.0release notes

  • Nulls are no longer dropped on pandas-like and Dask backends.

    2.28.0release notes

  • Consistently raises DuplicateError.

    2.28.0release notes

  • On Dask, var and std return null for N <= ddof and zero instead of null for constant group_by groups.

    2.28.0release notes

  • PyArrow cum_sum upcasts Int8, Int16, UInt8 and UInt16 inputs to Int64.

    2.27.0release notes

  • Floor division by zero returns null on pandas-like backends.

    2.27.0release notes

  • Invalid str.pad_start and str.pad_end arguments are rejected consistently across backends.

    2.27.0release notes

  • Negative offsets match Polars, and negative lengths raise an error.

    2.27.0release notes

  • Duplicate struct field names raise DuplicateError.

    2.27.0release notes

New APIs and options 4

  • Dask now supports list len, get, min, max, mean, median, sum, and sort operations.

    2.28.0release notes

  • DataFrame and LazyFrame gain a cast method for casting columns.

    2.27.0release notes

  • list.contains is supported for PyArrow, pandas and Dask.

    2.27.0release notes

  • Reader and scanner functions accept file-like objects.

    2.27.0release notes

Performance 2

  • Avoids copying NumPy arrays on pandas 3.

    2.28.0release notes

  • LazyFrame.cast no longer resolves the full schema just to check column names.

    2.27.0release notes

Behavior and default changes 2

  • Adds support for DuckDB 2.0 in joins, time zone lookup, and from_native typing.

    2.28.0release notes

  • Plugin support now extends to IO and from_* methods/functions.

    2.28.0release notes

Tooling 1

  • Narwhals hints at the narwhals-datafusion plugin when given a datafusion.DataFrame.

    2.27.0release notes

Fixes and other changes 37

  • Floor division on DuckDB is corrected for negative operands and floats.

    2.28.0release notes

  • Operations no longer raise an unhashable type error for cuDF categorical columns.

    2.28.0release notes

  • Corrects DuckDB duration results for durations of one hour or more.

    2.28.0release notes

  • Handles eager plugin native objects.

    2.28.0release notes

  • Handles eager plugin native objects.

    2.28.0release notes

  • Null handling in mode is fixed for SQL-like backends.

    2.28.0release notes

  • Modules that are still being imported are now ignored.

    2.28.0release notes

  • Scalar reduction results keep their dtype on the PyArrow backend.

    2.28.0release notes

  • Set difference between selectors is restored.

    2.28.0release notes

  • Selector union columns are returned in schema order.

    2.28.0release notes

  • Handles eager plugin native objects.

    2.28.0release notes

  • Invalid descending and reverse values raise consistent errors in sort and top_k.

    2.28.0release notes

  • Non-ASCII letters are treated as word characters on DuckDB, Spark-like, and old Polars backends.

    2.28.0release notes

  • Invalid descending and reverse values raise consistent errors in sort and top_k.

    2.28.0release notes

  • Corrects SQL backend results with ddof > 1, including over and null for N <= ddof.

    2.28.0release notes

  • Returns a numeric dtype for all-null object columns.

    2.27.1release notes

  • Counts characters rather than bytes on Polars < 2.0.

    2.27.1release notes

  • Casting to String preserves nulls on pandas before v3.0.0.

    2.27.0release notes

  • DuckDB diagonal concatenation uses the relations' own connection.

    2.27.0release notes

  • Boolean rendering aligns across pandas-like and Dask backends.

    2.27.0release notes

  • When ignore_nulls=True, pandas-like and Dask backends drop the trailing separator.

    2.27.0release notes

  • Behavior aligns with polars<0.20.6.

    2.27.0release notes

  • Scalar-only expressions are broadcast for SQL-like backends.

    2.27.0release notes

  • The PyArrow backend preserves all-null rows.

    2.27.0release notes

  • PySpark avoids DIVIDE_BY_ZERO for correlation on constant columns.

    2.27.0release notes

  • On pandas-like backends, cum_count(reverse=True) counts non-null values.

    2.27.0release notes

  • Dask aligns scalar operands before fill_null and horizontal reductions.

    2.27.0release notes

  • Pandas-like and PyArrow horizontal functions broadcast literals.

    2.27.0release notes

  • Null handling for list.contains on lazy backends now aligns with Polars.

    2.27.0release notes

  • Avoids name collisions for max_horizontal and min_horizontal on pandas-like backends.

    2.27.0release notes

  • Dask aligns series before fillna and isna in mean_horizontal.

    2.27.0release notes

  • __mod__ and __rmod__ behavior with negative operands aligns across backends.

    2.27.0release notes

  • PyArrow uses native starts_with and ends_with kernels, fixing empty-suffix ends_with.

    2.27.0release notes

  • str.replace(n=0) works on pandas-like backends.

    2.27.0release notes

  • A negative width is rejected consistently across backends.

    2.27.0release notes

  • str.zfill(0) works on PyArrow-backed data.

    2.27.0release notes

  • Corrects handling of plus-prefixed strings on polars<=1.30 and supports polars 0.20.4.

    2.27.0release notes