{"record":{"id":"8bb21a6f6cf936d0","repo":"apache/beam","slug":"please-specify-exactly-one-of-row-key-or-a-lambda-function","errorCode":null,"errorMessage":"Please specify exactly one of `row_key` or a lambda function with `row_key_fn` to extract the row key from the input row.","messagePattern":"Please specify exactly one of `row_key` or a lambda function with `row_key_fn` to extract the row key from the input row\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/transforms/enrichment_handlers/bigtable.py","lineNumber":95,"sourceCode":"      app_profile_id: str = None,  # type: ignore[assignment]\n      encoding: str = 'utf-8',\n      row_key_fn: Optional[RowKeyFn] = None,\n      exception_level: ExceptionLevel = ExceptionLevel.WARN,\n      include_timestamp: bool = False,\n  ):\n    self._project_id = project_id\n    self._instance_id = instance_id\n    self._table_id = table_id\n    self._row_key = row_key\n    self._row_filter = row_filter\n    self._app_profile_id = app_profile_id\n    self._encoding = encoding\n    self._row_key_fn = row_key_fn\n    self._exception_level = exception_level\n    self._include_timestamp = include_timestamp\n    if ((not self._row_key_fn and not self._row_key) or\n        bool(self._row_key_fn and self._row_key)):\n      raise ValueError(\n          \"Please specify exactly one of `row_key` or a lambda \"\n          \"function with `row_key_fn` to extract the row key \"\n          \"from the input row.\")\n\n  def __enter__(self):\n    \"\"\"connect to the Google BigTable cluster.\"\"\"\n    self.client = Client(project=self._project_id)\n    self.instance = self.client.instance(self._instance_id)\n    self._table = bigtable.table.Table(\n        table_id=self._table_id,\n        instance=self.instance,\n        app_profile_id=self._app_profile_id)\n\n  def __call__(self, request: beam.Row, *args, **kwargs):\n    \"\"\"\n    Reads a row from the GCP BigTable and returns\n    a `Tuple` of request and response.\n","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/transforms/enrichment_handlers/bigtable.py#L77-L113","documentation":"Raised by BigTableEnrichmentHandler.__init__ when row-key configuration is ambiguous or missing: the handler requires exactly one way to determine the BigTable row key — either a static `row_key` string or a `row_key_fn` callable that extracts it from the input row. Passing neither, or passing both, is rejected at construction time.","triggerScenarios":"bigtable.BigTableEnrichmentHandler(instance_id=..., table_id=...) with neither row_key nor row_key_fn; or with both row_key='somekey' and row_key_fn=lambda row: ... simultaneously.","commonSituations":"Copy-pasting example code that sets row_key and then adding a row_key_fn for dynamic keys; forgetting both arguments when converting a handler from static to dynamic keys; refactoring that left a stale row_key in place.","solutions":["Pass exactly one of `row_key` (static string) or `row_key_fn` (callable extracting the key from the beam.Row).","If keys vary per element, remove the static `row_key` and supply `row_key_fn=lambda row: row['my_key']`.","If the key is always the same, keep `row_key='...'` and delete the `row_key_fn` argument."],"exampleFix":"# before (both supplied)\nh = bigtable.BigTableEnrichmentHandler(instance_id=i, table_id=t, row_key='k', row_key_fn=lambda r: r['id'])\n# after (dynamic key only)\nh = bigtable.BigTableEnrichmentHandler(instance_id=i, table_id=t, row_key_fn=lambda r: r['id'])","handlingStrategy":"validation","validationCode":"def make_bigtable_handler(row_key=None, row_key_fn=None, **kw):\n    if bool(row_key) == bool(row_key_fn):\n        raise ValueError('specify exactly one of row_key or row_key_fn')\n    return bigtable.BigTableEnrichmentHandler(row_key=row_key, row_key_fn=row_key_fn, **kw)","typeGuard":"def valid_row_key_config(row_key, row_key_fn):\n    return (row_key is None) != (row_key_fn is None)","tryCatchPattern":"try:\n    handler = bigtable.BigTableEnrichmentHandler(**cfg)\nexcept ValueError as e:\n    logging.error('row key config invalid: %s', e)\n    raise","preventionTips":["Use a factory/builder that enforces one-of row_key/row_key_fn.","When migrating to dynamic keys, grep for leftover row_key arguments.","Document which configuration style your pipeline uses."],"tags":["python","apache-beam","bigtable","configuration","argument-validation"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T21:17:11.552Z"}