apache/beam · error · RuntimeError

histogram has no record.

Error message

histogram has no record.

What it means

Percentile interpolation is undefined on an empty histogram. When total_count() is 0, Beam's _get_linear_interpolation raises RuntimeError instead of returning a meaningless value. Reached via get_linear_interpolation/p50/p90/p99 or get_percentile_info on a histogram with no recorded data.

Solutions

  1. Guard with h.total_count() > 0 before querying percentiles.
  2. Return a sentinel (e.g. None or NaN) when empty in caller code.
  3. Ensure record() is invoked for all expected elements before percentile reporting.
  4. In tests, seed the histogram with sample records first.

Example fix

// before
latency = h.p99()
// after
latency = h.p99() if h.total_count() > 0 else None
Defensive patterns

Strategy: try-catch

Validate before calling

if h.total_count() == 0:
    percentile_value = None
else:
    percentile_value = h.p99()

Try / catch

try:
    v = h.p99()
except RuntimeError:
    v = None  # empty histogram

Prevention

When it happens

Trigger: Calling h.p99() before any record() calls; querying a freshly deserialized or copied empty histogram; querying after combine with two empty histograms.

Common situations: Metrics reported before the pipeline processed any elements; windowed/filtered pipelines where a window got zero records; unit tests instantiating Histogram without seeding data.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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

Appendix: source

Thrown at sdks/python/apache_beam/utils/histogram.py:143

    It first finds the bucket which includes the target percentile and
    projects the estimated point in the bucket by assuming all the elements
    in the bucket are uniformly distributed.

    Args:
      percentile: The target percentile of the value returning from this
        method. Should be a floating point number greater than 0 and less
        than 1.
    """
    if percentile > 1 or percentile < 0:
      raise ValueError('percentile should be between 0 and 1.')
    with self._lock:
      return self._get_linear_interpolation(percentile)

  def _get_linear_interpolation(self, percentile):
    total_num_records = self.total_count()
    if total_num_records == 0:
      raise RuntimeError('histogram has no record.')

    index = 0
    record_sum = self._num_bot_records
    if record_sum / total_num_records >= percentile:
      return float('-inf')
    while index < self._bucket_type.num_buckets():
      record_sum += self._buckets.get(index, 0)
      if record_sum / total_num_records >= percentile:
        break
      index += 1
    if index == self._bucket_type.num_buckets():
      return float('inf')

    frac_percentile = percentile - (
        record_sum - self._buckets[index]) / total_num_records
    bucket_percentile = self._buckets[index] / total_num_records
    frac_bucket_size = frac_percentile * self._bucket_type.bucket_size(
        index) / bucket_percentile

View on GitHub (pinned to 12126d8942)