apache/beam · error · TypeError

'Expected GaugeData metric type but received %s with value %

Error message

'Expected GaugeData metric type but received %s with value %s' % (type(metric), metric)

What it means

int64_user_gauge builds a user gauge MonitoringInfo and requires the metric to be a GaugeData instance carrying both value and timestamp. Passing any other object raises TypeError so a bare number or wrong type is never silently encoded as a gauge. This is a fail-fast input-type check during metric construction.

Source

Thrown at sdks/python/apache_beam/metrics/monitoring_infos.py:298


def int64_user_gauge(
    namespace, name, metric, ptransform=None) -> metrics_pb2.MonitoringInfo:
  """Return the gauge monitoring info for the URN, metric and labels.

  Args:
    namespace: User-defined namespace of gauge metric.
    name: Name of gauge metric.
    metric: The GaugeData containing the metrics.
    ptransform: The ptransform id used as a label.
  """
  labels = create_labels(ptransform=ptransform, namespace=namespace, name=name)
  if isinstance(metric, GaugeData):
    coder = coders.VarIntCoder()
    value = metric.value
    timestamp = metric.timestamp
  else:
    raise TypeError(
        'Expected GaugeData metric type but received %s with value %s' %
        (type(metric), metric))
  payload = _encode_gauge(coder, timestamp, value)
  return create_monitoring_info(
      USER_GAUGE_URN, LATEST_INT64_TYPE, payload, labels)


def int64_gauge(urn, metric, ptransform=None) -> metrics_pb2.MonitoringInfo:
  """Return the gauge monitoring info for the URN, metric and labels.

  Args:
    urn: The URN of the monitoring info/metric.
    metric: An int representing the value. The current time will be used for
            the timestamp.
    ptransform: The ptransform id used as a label.
  """
  labels = create_labels(ptransform=ptransform)
  if isinstance(metric, int):

View on GitHub (pinned to 12126d8942)

Solutions

  1. Wrap the value in GaugeData before calling: metric=GaugeData(value, timestamp=...).
  2. If you have a plain int, call int64_gauge instead, which accepts ints.
  3. Add an isinstance(metric, GaugeData) check before the call with a clear app-level error.

Example fix

// before
mi = int64_user_gauge(ptransform=pt, namespace='ns', name='latency', metric=42)
// after
from apache_beam.metrics.execution import GaugeData
mi = int64_user_gauge(ptransform=pt, namespace='ns', name='latency', metric=GaugeData(42))
Defensive patterns

Strategy: type-guard

Validate before calling

from apache_beam.metrics.execution import GaugeData
if not isinstance(metric, GaugeData):
    metric = GaugeData(metric)

Type guard

def is_gauge_data(m):
    return isinstance(m, GaugeData)

Try / catch

try:
    mi = int64_user_gauge(ptransform=pt, namespace=ns, name=name, metric=metric)
except TypeError as e:
    logger.error('user gauge requires GaugeData: %s', e)
    raise

Prevention

When it happens

Trigger: Calling int64_user_gauge with an int, float, string, or None instead of a GaugeData instance, e.g. int64_user_gauge(ptransform=..., namespace=..., name=..., metric=42).

Common situations: Confusing int64_user_gauge (expects GaugeData) with int64_gauge (expects int); copying code between the two gauge builders; wrapping raw metric values read from another pipeline component.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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