apache/beam · error · TypeError
: filters must be a sequence of tuple with length=3 got %r…
Error message
%s: filters must be a sequence of tuple with length=3 got %r instead
What it means
When converting a Beam Query for the Cloud Datastore v1 client, each filter must be a 3-tuple (property, operator, value). _set_runtime_filters checks every tuple has length exactly 3 and raises TypeError otherwise, because a malformed filter cannot be mapped onto the structured-query proto.
Solutions
- Ensure every entry in query.filters is a (property, operator, value) 3-tuple.
- If the value is missing, supply it or use an operator form that takes one, e.g. ('age', '>', 0).
- When using templates, each element may be a ValueProvider, but the tuple itself must still have exactly three ValueProvider/str elements.
- Validate filters at pipeline-construction time with a small assertion loop before creating the Query.
Example fix
// before
query = Query(kind='Person', filters=[('age', '>')])
// after
query = Query(kind='Person', filters=[('age', '>', 30)]) Defensive patterns
Strategy: validation
Validate before calling
def check_filters(filters):
for f in filters:
if not (isinstance(f, tuple) and len(f) == 3):
raise TypeError(f'Filter must be (prop, op, value) 3-tuple, got {f!r}') Try / catch
try:
client_query = query._to_client_query()
except TypeError as e:
raise PipelineError(f'Malformed Datastore filters: {e}') from e Prevention
- Always build filters as (property, operator, value) tuples
- Keep ValueProviders inside the tuple, not as the tuple itself
- Assert filter shape in unit tests for template pipelines
When it happens
Trigger: Building Query(..., filters=[...]) with a tuple of length 1, 2, or 4 (e.g. forgetting the value: ('age', '>')), passing a non-iterable filter, or appending filters of the wrong shape at runtime via _to_client_query.
Common situations: Migrating from other Datastore client libraries where filters are method calls (add_filter(prop, op, value)) rather than tuples; developers port code and pass 2-tuples, or build filters dynamically and accidentally drop an element.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Query cannot have any inequality filters.
- Unexpected type of id_or_name
- A cluster_identifier should be Optional[Union[str…
- Cannot convert from a JSON value.
- Cannot convert to a JSON value.
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/96b64dd2ed6ab7dc.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/io/gcp/datastore/v1new/types.py:120
kind=self.kind,
project=self.project,
namespace=self.namespace,
ancestor=ancestor_client_key,
filters=self.filters,
projection=self.projection,
order=self.order,
distinct_on=self.distinct_on)
def _set_runtime_filters(self):
"""
Extracts values from ValueProviders in `self.filters` if available
:param filters: sequence of tuple[str, str, str] or
sequence of tuple[ValueProvider, ValueProvider, ValueProvider]
:return: tuple[str, str, str]
"""
runtime_filters = []
if not all(len(filter_tuple) == 3 for filter_tuple in self.filters):
raise TypeError(
'%s: filters must be a sequence of tuple with length=3'
' got %r instead' % (self.__class__.__name__, self.filters))
for filter_type, filter_operator, filter_value in self.filters:
if isinstance(filter_type, ValueProvider):
filter_type = filter_type.get()
if isinstance(filter_operator, ValueProvider):
filter_operator = filter_operator.get()
if isinstance(filter_value, ValueProvider):
filter_value = filter_value.get()
runtime_filters.append((filter_type, filter_operator, filter_value))
return runtime_filters or ()
def clone(self):
return copy.copy(self)
def __repr__(self):View on GitHub (pinned to 12126d8942)