{"record":{"id":"43dbd9ff1a71422f","repo":"apache/beam","slug":"metric-name-must-be-non-empty","errorCode":null,"errorMessage":"Metric name must be non-empty","messagePattern":"Metric name must be non-empty","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/metrics/metricbase.py","lineNumber":80,"sourceCode":"      urn: Optional[str] = None,\n      labels: Optional[dict[str, str]] = None) -> None:\n    \"\"\"Initializes ``MetricName``.\n\n    Note: namespace and name should be set for user metrics,\n    urn and labels should be set for an arbitrary metric to package into a\n    MonitoringInfo.\n\n    Args:\n      namespace: A string with the namespace of a metric.\n      name: A string with the name of a metric.\n      urn: URN to populate on a MonitoringInfo, when sending to RunnerHarness.\n      labels: Labels to populate on a MonitoringInfo\n    \"\"\"\n    if not urn:\n      if not namespace:\n        raise ValueError('Metric namespace must be non-empty')\n      if not name:\n        raise ValueError('Metric name must be non-empty')\n    self.namespace = namespace\n    self.name = name\n    self.urn = urn\n    self.labels = labels if labels else {}\n\n  def __eq__(self, other):\n    return (\n        self.namespace == other.namespace and self.name == other.name and\n        self.urn == other.urn and self.labels == other.labels)\n\n  def __str__(self):\n    if self.urn:\n      return 'MetricName(namespace={}, name={}, urn={}, labels={})'.format(\n          self.namespace, self.name, self.urn, self.labels)\n    else:  # User counter case.\n      return 'MetricName(namespace={}, name={})'.format(\n          self.namespace, self.name)\n","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/metrics/metricbase.py#L62-L98","documentation":"Metric.__init__ raises ValueError when no MonitoringInfo URN is given and the metric name is empty. Beam requires namespace+name to uniquely identify a user metric when no urn is provided, so an empty name makes the metric unidentifiable. The check runs only when urn is falsy.","triggerScenarios":"Calling Metrics.counter/counter distribution/gauge (or Metric directly) with name='' or None and no urn, e.g. Metrics.counter('MyDoFn', '') or name pulled from an empty variable.","commonSituations":"Metric names built from f-strings or config values that resolve to empty; refactoring where the literal name was accidentally removed; constructing metrics in a loop over a list containing empty strings.","solutions":["Pass a non-empty metric name string, e.g. Metrics.counter('MyDoFn', 'elements_read').","Supply a urn argument instead; with a urn set, name/namespace validation is skipped.","Validate the name before constructing the metric and raise a clearer app-level error."],"exampleFix":"// before\n_read = Metrics.counter('MyDoFn', metric_name)  # metric_name == ''\n// after\nassert metric_name, 'metric name required'\n_read = Metrics.counter('MyDoFn', metric_name or 'elements_read')","handlingStrategy":"validation","validationCode":"if not urn and not name:\n    raise ValueError('metric name required when urn is not set')\nmetric = Metrics.counter(namespace, name)","typeGuard":null,"tryCatchPattern":"try:\n    metric = Metrics.counter(namespace, name)\nexcept ValueError:\n    logger.exception('invalid metric name %r', name)\n    raise","preventionTips":["Use literal string names for metrics instead of dynamically computed ones where possible.","Validate names built from f-strings/config before constructing metrics."],"tags":["python","apache-beam","metrics","validation"],"backgroundTag":"empty-required-field","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}