Polars DataFrame Filter: The Always-True (No-Op) Predicate

Searching for a "Polars DataFrame filter always true predicate" usually means one of two things: you want a filter that keeps every row, or you're building predicates dynamically and need a neutral starting point. Here's the thing to clear up first — Polars has no dedicated "always-true" filter function. There's no pl.true(), no always_true flag, no special sentinel. The idiomatic no-op predicate is simply pl.lit(True). This guide shows the correct syntax, why you'd want it, the difference between pl.lit(True) and a bare Python True, and a few historical edge cases that used to bite people.

TL;DR: To filter a Polars DataFrame with an always-true predicate (keep all rows), use df.filter(pl.lit(True)). A bare df.filter(True) also works on current versions. There is no dedicated always-true function — pl.lit(True) is the idiom.

All code below was verified on Polars 1.42.1 (the latest release as of 2026-07-14; verify the current version on PyPI).

The correct syntax for an always-true filter

The filter method keeps rows where the predicate evaluates to True and discards everything else, including nulls. To keep every row, hand it a predicate that is True for all of them:

import polars as pl
 df = pl.DataFrame({"foo": [1, 2, 3], "bar": ["a", "b", "c"]})  df.filter(pl.lit(True))   # returns all 3 rows — a no-op filter

pl.lit(True) builds a literal boolean expression. Polars broadcasts that single True across the DataFrame's length, so every row passes. The same idiom works on a LazyFrame:

df.lazy().filter(pl.lit(True)).collect()   # all rows

That's the whole answer. But the reason people search for this is more interesting than the syntax.

Why use an always-true predicate at all?

An always-true predicate is the identity element for logical AND. If you're assembling a filter programmatically — say, from a list of optional conditions supplied by a user or config — you need a neutral value to start from and combine onto. True is that value:

predicate = pl.lit(True)              # neutral starting point  conditions = [pl.col("foo") > 1]      # could be empty, could have many for cond in conditions:     predicate = predicate & cond      # AND them together  df.filter(predicate)                  # 2 rows

If conditions is empty, the loop never runs and predicate stays pl.lit(True), so filter correctly returns the whole DataFrame instead of raising or filtering to nothing. Without a neutral start, you'd have to special-case the "no conditions" branch.

The mirror image is the always-false predicate, pl.lit(False), which is the identity element for logical OR. Start from pl.lit(False) when you're OR-ing conditions together and want "no conditions" to mean "no rows."

pl.lit(True) vs a bare Python True

You may have seen both forms floating around. Here's how they compare:

  • df.filter(pl.lit(True)) — explicit literal expression. Recommended.
  • df.filter(True) — Polars accepts a bare Python bool and wraps it as a literal internally. Works on current versions.

Both return all rows in a simple no-op. So why prefer pl.lit(True)?

  1. Clarity of intent. pl.lit(True) reads as "a literal expression," which is what filter expects.
  2. Safety when combining. When you combine a predicate with & or |, wrapping the boolean in pl.lit() keeps you firmly in Polars' expression semantics rather than relying on Python's operator resolution. This matters more in older Polars versions, where combining a bare True with | produced surprising results (see the edge cases below).

A quick contrast:

# always-true OR'd with a condition = still everyone 
df.filter(pl.lit(True) | (pl.col("foo") == 1)) # 3 rows # always-false AND'd with a condition = nobody df.filter(pl.lit(False) & (pl.col("foo") == 1)) # 0 rows

What about filtering a Series?

The pl.lit(True) trick is a DataFrame/LazyFrame idiom. Series.filter expects an actual boolean mask of matching length, not a scalar literal expression. Historically, series.filter(pl.lit(True)) raised an AttributeError because a Series doesn't evaluate expressions the way a frame does. If you're at the Series level and want a no-op, build a full-length boolean mask instead:

s = pl.Series([1, 2, 3]) s.filter(pl.Series([True, True, True]))   # keeps all three

In practice, if you're reaching for an always-true predicate you're almost always working with a frame, where pl.lit(True) is correct.

Historical edge cases worth knowing

A no-op filter sounds like it should never misbehave, but two now-fixed bugs are worth knowing if you're pinned to an older Polars version.

Rowless DataFrame added a phantom row

Between versions 0.19.19 and 0.20.0, filtering a rowless (zero-row) DataFrame with pl.lit(True) incorrectly produced a single row of nulls. This was reported as issue #16664 and subsequently fixed. On 1.42.1 the behavior is correct — a rowless frame stays rowless:

pl.DataFrame({"x": []}).filter(pl.lit(True)).shape   # (0, 1)  ✓

All-null column raised a ShapeError

In version 1.13.0, df.filter(pl.lit(True)) raised ShapeError: filter's length: 1 differs from that of the series: 2 when the DataFrame contained an all-null column (issue #19771). The literal wasn't being broadcast to the frame's length in that specific case. This was fixed by the maintainers, and on 1.42.1 it works as expected:

pl.DataFrame({"a": [None, None]}).filter(pl.lit(True)).height   # 2  ✓

Takeaway: these were genuine regressions, not intended behavior. If you hit odd results from a no-op filter, check your Polars version first and upgrade — the current release handles empty frames, all-null columns, and combined predicates correctly.

Does the query optimizer strip out an always-true filter?

In the lazy API, Polars runs optimization passes over your query plan. A constant pl.lit(True) predicate is a prime candidate for simplification, and recent releases have expanded predicate handling — Polars 1.42 added optimizer elimination of contradictory filter predicates, per the Polars blog. The exact set of simplifications applied to a literal-true predicate can change release to release. [VERIFY] — if you depend on the optimizer removing a no-op filter for performance, confirm it against df.lazy().filter(pl.lit(True)).explain() on your specific version rather than assuming.

Quick reference

GoalExpressionResult
Keep every row (no-op)df.filter(pl.lit(True))all rows
Keep every row (shorthand)df.filter(True)all rows
Drop every rowdf.filter(pl.lit(False))0 rows
Neutral start for AND-chainspred = pl.lit(True) then pred &= condAND identity
Neutral start for OR-chainspred = pl.lit(False) then `pred= cond`

Conclusion

The short version: there is no special always-true filter function in Polars, and you don't need one. Use pl.lit(True) for a no-op predicate that keeps every row, use pl.lit(False) to drop them all, and lean on pl.lit(True) as the identity element when you build filter predicates dynamically. A bare Python True works too on current versions, but the explicit literal reads better and sidesteps old operator-combination footguns.

If you're on an older release and a no-op filter behaves strangely with empty frames or all-null columns, upgrade — those were bugs, now fixed. Next step: check your installed version with pl.__version__, and skim the official DataFrame.filter docs for the full predicate and constraint syntax.

 

References