# What changed in narwhals

> 57 changes in narwhals 2 from its official release notes, upgrade guides and advisories: 11 breaking, 4 new APIs and options. Each one cited. Sources checked 2026-10-30. HTML: https://unstale.sh/pypi/narwhals/

To see which of these apply to a repository, run `npx @unstale/cli init` in it.

## narwhals 2

### Breaking changes

- Returns null when no valid values exist. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- Returns null when no valid values exist. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- Mismatched items raise InvalidOperationError on pyarrow-backed backends. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- Nulls are no longer dropped on pandas-like and Dask backends. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- Consistently raises DuplicateError. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- On Dask, var and std return null for N <= ddof and zero instead of null for constant group_by groups. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- PyArrow cum_sum upcasts Int8, Int16, UInt8 and UInt16 inputs to Int64. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- Floor division by zero returns null on pandas-like backends. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- Invalid str.pad_start and str.pad_end arguments are rejected consistently across backends. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- Negative offsets match Polars, and negative lengths raise an error. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- Duplicate struct field names raise DuplicateError. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)

### New APIs and options

- Dask now supports list len, get, min, max, mean, median, sum, and sort operations. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- DataFrame and LazyFrame gain a cast method for casting columns. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- list.contains is supported for PyArrow, pandas and Dask. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- Reader and scanner functions accept file-like objects. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)

### Performance

- Avoids copying NumPy arrays on pandas 3. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- LazyFrame.cast no longer resolves the full schema just to check column names. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)

### Behavior and default changes

- Adds support for DuckDB 2.0 in joins, time zone lookup, and from_native typing. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- Plugin support now extends to IO and from_* methods/functions. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)

### Tooling

- Narwhals hints at the narwhals-datafusion plugin when given a datafusion.DataFrame. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)

### Fixes and other changes

- Floor division on DuckDB is corrected for negative operands and floats. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- Operations no longer raise an unhashable type error for cuDF categorical columns. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- Corrects DuckDB duration results for durations of one hour or more. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- Handles eager plugin native objects. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- Handles eager plugin native objects. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- Null handling in mode is fixed for SQL-like backends. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- Modules that are still being imported are now ignored. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- Scalar reduction results keep their dtype on the PyArrow backend. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- Set difference between selectors is restored. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- Selector union columns are returned in schema order. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- Handles eager plugin native objects. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- Invalid descending and reverse values raise consistent errors in sort and top_k. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- Non-ASCII letters are treated as word characters on DuckDB, Spark-like, and old Polars backends. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- Invalid descending and reverse values raise consistent errors in sort and top_k. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- Corrects SQL backend results with ddof > 1, including over and null for N <= ddof. (2.28.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.28.0)
- Returns a numeric dtype for all-null object columns. (2.27.1) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.1)
- Counts characters rather than bytes on Polars < 2.0. (2.27.1) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.1)
- Casting to String preserves nulls on pandas before v3.0.0. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- DuckDB diagonal concatenation uses the relations' own connection. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- Boolean rendering aligns across pandas-like and Dask backends. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- When ignore_nulls=True, pandas-like and Dask backends drop the trailing separator. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- Behavior aligns with polars<0.20.6. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- Scalar-only expressions are broadcast for SQL-like backends. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- The PyArrow backend preserves all-null rows. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- PySpark avoids DIVIDE_BY_ZERO for correlation on constant columns. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- On pandas-like backends, cum_count(reverse=True) counts non-null values. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- Dask aligns scalar operands before fill_null and horizontal reductions. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- Pandas-like and PyArrow horizontal functions broadcast literals. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- Null handling for list.contains on lazy backends now aligns with Polars. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- Avoids name collisions for max_horizontal and min_horizontal on pandas-like backends. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- Dask aligns series before fillna and isna in mean_horizontal. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- __mod__ and __rmod__ behavior with negative operands aligns across backends. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- PyArrow uses native starts_with and ends_with kernels, fixing empty-suffix ends_with. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- str.replace(n=0) works on pandas-like backends. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- A negative width is rejected consistently across backends. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- str.zfill(0) works on PyArrow-backed data. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
- Corrects handling of plus-prefixed strings on polars<=1.30 and supports polars 0.20.4. (2.27.0) — [release notes](https://github.com/narwhals-dev/narwhals/releases/tag/v2.27.0)
