{"record":{"id":"05c792e36d8801d1","repo":"apache/beam","slug":"either-where-clause-fields-or-where-clause-value-fn-must-be","errorCode":null,"errorMessage":"Either where_clause_fields or where_clause_value_fn must be specified","messagePattern":"Either where_clause_fields or where_clause_value_fn must be specified","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/transforms/enrichment_handlers/cloudsql.py","lineNumber":610,"sourceCode":"\n    Args:\n      template: SQL template string with named parameters (e.g., \"id = :id\")\n\n    Returns:\n      List of parameter names found in the template (e.g., [\"id\"])\n    \"\"\"\n    return re.findall(r':(\\w+)', template)\n\n  def create_row_key(self, row: beam.Row):\n    if isinstance(self._query_config, TableFunctionQueryConfig):\n      return tuple(self._query_config.where_clause_value_fn(row))\n    if isinstance(self._query_config, TableFieldsQueryConfig):\n      row_dict = row._asdict()\n      return (\n          tuple(\n              row_dict[where_clause_field]\n              for where_clause_field in self._query_config.where_clause_fields))\n    raise ValueError(\n        \"Either where_clause_fields or where_clause_value_fn must be specified\")\n\n  def get_cache_key(self, request: Union[beam.Row, list[beam.Row]]):\n    if isinstance(self._query_config, CustomQueryConfig):\n      raise NotImplementedError(\n          \"Caching is not supported for CustomQueryConfig. \"\n          \"Consider using TableFieldsQueryConfig or \" +\n          \"TableFunctionQueryConfig instead.\")\n\n    if isinstance(request, list):\n      cache_keys = []\n      for req in request:\n        req_dict = req._asdict()\n        try:\n          if isinstance(self._query_config, TableFunctionQueryConfig):\n            current_values = self._query_config.where_clause_value_fn(req)\n          elif isinstance(self._query_config, TableFieldsQueryConfig):\n            current_values = [","sourceCodeStart":592,"sourceCodeEnd":628,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/transforms/enrichment_handlers/cloudsql.py#L592-L628","documentation":"create_row_key builds a dedup/batch key from each row. For TableFieldsQueryConfig it tuples the where_clause_fields values; for any other config type without where_clause_fields it raises ValueError saying where_clause_fields or where_clause_value_fn must be specified.","triggerScenarios":"Batched enrichment (_process_batch_request calls create_row_key) with a query config that is not TableFieldsQueryConfig and provides no where_clause_fields / where_clause_value_fn, e.g. CustomQueryConfig.","commonSituations":"Using CustomQueryConfig with batched lookups; forgetting to populate where_clause_fields; switching configs without updating batch settings.","solutions":["Use TableFieldsQueryConfig with where_clause_fields set for batched requests.","Disable batching and use single-request processing for CustomQueryConfig.","Ensure the passed config type supports row-key generation."],"exampleFix":"# before\nhandler = CloudSQLEnrichmentHandler(query_config=CustomQueryConfig(query=...), batch_lookup=True, ...)\n# after\nhandler = CloudSQLEnrichmentHandler(query_config=TableFieldsQueryConfig(table_name=\"users\", table_fields=[\"id\"], where_clause_template=\"id = {id}\", where_clause_fields=[\"id\"]), batch_lookup=True, ...)","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":["python","cloudsql","batching","configuration"],"backgroundTag":"missing-required-config-field","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}