apache/beam · error · ValueError

no matching row found for query

Error message

no matching row found for query: {query}

What it means

In the batched __call__ path, after executing the query, requests that got no matching BigQuery row remain unmatched. If throw_exception_on_empty_results is True, a ValueError naming the query is raised; otherwise a warning is logged and empty rows are returned.

Solutions

  1. Set throw_exception_on_empty_results=False if empty results are acceptable (warning + empty Row returned instead)
  2. Verify key types match between input rows and the BigQuery table (e.g. cast id to STRING)
  3. Check the row_restriction_template/query filters aren't excluding valid rows
  4. Confirm the lookup values exist in the table

Example fix

// before
BigQueryEnrichmentHandler(..., throw_exception_on_empty_results=True)
// after
BigQueryEnrichmentHandler(..., throw_exception_on_empty_results=False)
Defensive patterns

Strategy: fallback

Validate before calling

def normalize_key(v):
    return str(v).strip()
# ensure both sides of the join use the same normalization before enrichment

Try / catch

try:
    out = handler(rows)
except ValueError as e:
    if 'no matching row' in str(e):
        out = [(r, beam.Row()) for r in rows]
    else:
        raise

Prevention

When it happens

Trigger: Batched call where none of the returned BigQuery rows match the keys of the submitted requests (keys don't join), with throw_exception_on_empty_results=True.

Common situations: Type mismatch between the enrichment-table key and the input key (int vs string); row_restriction_template filtering out all rows; data genuinely missing in the table.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/c71c91129192c5fa. Report an issue: GitHub.

Appendix: source

Thrown at sdks/python/apache_beam/transforms/enrichment_handlers/bigquery.py:237

        values.extend(current_values)
        requests_map[self.create_row_key(req)].append(req)
      query = raw_query.format(*values)

      responses_dict = self._execute_query(query)
      unmatched_requests = {
          key: list(reqs)
          for key, reqs in requests_map.items()
      }
      if responses_dict:
        for response in responses_dict:
          response_row = beam.Row(**response)
          response_key = self.create_row_key(response_row)
          if response_key in unmatched_requests:
            for req in unmatched_requests.pop(response_key):
              responses.append((req, response_row))
      if unmatched_requests:
        if self.throw_exception_on_empty_results:
          raise ValueError(f"no matching row found for query: {query}")
        else:
          _LOGGER.warning('no matching row found for query: %s', query)
          for reqs in unmatched_requests.values():
            for req in reqs:
              responses.append((req, beam.Row()))
      return responses
    else:
      request_dict = request._asdict()
      if self.query_fn:
        # if a query_fn is provided then it return a list of values
        # that should be populated into the query template string.
        query = self.query_fn(request)
      else:
        values = (
            self.condition_value_fn(request) if self.condition_value_fn else
            list(map(request_dict.get, self.fields)))
        # construct the query.
        query = self.query_template.format(*values)

View on GitHub (pinned to 12126d8942)