Docs/Error messages/Cannot query over table without a filter
Error messagesCost

Cannot query over table without a filter over columns that can be used for partition elimination

The table has require_partition_filter set, so BigQuery refuses any query that cannot prune partitions before reading. Which filters count is specific, and a subquery or an OR does not.

Cannot query over table 'bigquery-public-data.wikipedia.pageviews_2024' without a filter over column(s) 'datehour' that can be used for partition elimination

What BigQuery means

Somebody set require_partition_filter = TRUE on that table, and your query gives BigQuery no way to work out which partitions it needs before it starts reading.

The flag is a guard rail. The table is large enough that a full scan is expensive, so whoever owns it made the filter mandatory. The error itself is cheap, because it happens at planning time, so nothing is read and nothing is billed.

Note that the message names the partitioning column for you. That is the column your filter has to be on.

The smallest query that reproduces it

SELECT COUNT(*) FROM `bigquery-public-data.wikipedia.pageviews_2024`

Even COUNT(*) is refused. BigQuery does not make an exception for queries that happen not to read column data.

The fix

Filter on the column the message names, with values it can evaluate before the query runs:

SELECT COUNT(*)
FROM `bigquery-public-data.wikipedia.pageviews_2024`
WHERE datehour >= '2024-01-01' AND datehour < '2024-01-02'

Which filters count

The test is whether BigQuery can reduce the partition list before it reads anything. Mentioning the column is not enough.

These work:

FilterWhy
WHERE datehour = '2024-01-01'a constant
WHERE datehour BETWEEN '2024-01-01' AND '2024-01-02'a constant range
WHERE datehour > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 DAY)a function of constants, evaluated at planning time
WHERE datehour = '2024-01-01' OR datehour = '2024-01-02'every branch of the OR restricts the partition column
WHERE DATE(datehour) = '2024-01-01'accepted, though it prunes less well than a direct comparison
... FROM t JOIN (SELECT TIMESTAMP '2024-01-01' AS d) b ON t.datehour = b.da join condition counts, not just a WHERE
a WHERE in the outer query over a CTE that selects from the tableBigQuery pushes the filter down into the CTE
FROM t |> WHERE datehour = '2024-01-01'pipe syntax counts the same as a WHERE clause
WHERE datehour IS NOT NULLpasses the check, but matches every partition, so it silences the error without saving anything

These do not:

FilterWhy
WHERE datehour = '2024-01-01' OR views > 5the second branch lets any partition through
WHERE datehour >= (SELECT MIN(datehour) FROM ...)the value is not known until the subquery runs
no WHERE at all, including in a pipe query that goes straight to |> AGGREGATEnothing to prune with

The subquery case looks wrong because the query does filter on the right column. BigQuery needs the partition list before it executes anything, and a subquery result is not available then. If you need a dynamic bound, run it as two statements and put the first result into a scripting variable, or widen the filter to a constant range you know contains the answer.

Ingestion-time partitioned tables

If the table is partitioned by ingestion time rather than by a column of its own, there is no real column to filter on. Filter on the pseudocolumn instead:

SELECT COUNT(*) FROM `my-project.logs.events`
WHERE _PARTITIONTIME = TIMESTAMP '2026-10-01'

_PARTITIONTIME holds the ingestion time truncated to the partition boundary, hourly or daily or whatever the table uses. Daily-partitioned tables also have _PARTITIONDATE, the UTC date of that same value, which is easier to filter against. It does not exist on hourly, monthly or yearly tables, so _PARTITIONTIME is the one that always works. See Partitioning.

Turning it off

If you own the table and the requirement is in your way:

ALTER TABLE `my-project.logs.events` SET OPTIONS (require_partition_filter = FALSE)

Think about it first. The flag is usually there because someone has already paid for the full scan once.

Variants

MessageCause
the same text naming several columnsan externally partitioned (Hive-style) table with more than one partition key
Custom quota exceeded: Your usage exceeded the custom quota for QueryUsagePerDaya daily byte quota set by an admin, not a partition requirement

The job’s error_result.reason is invalidQuery.

In Querylab.io

Querylab.io warns about a partitioned table with no filter on its partitioning column, before you run the query, with a quick fix that adds the WHERE clause. The warning covers every partitioned table, not only the ones with require_partition_filter set, because the cost argument is the same either way. On the wikipedia table above it also reports the size of the scan and offers to add a TABLESAMPLE.

See Cost limits and How a query is billed.