prometheus/prometheus · warning · Error

Only one bucket in histogram ([-0, 0]). Cannot calculate def

Error message

Only one bucket in histogram ([-0, 0]). Cannot calculate defaultExpBucketWidth.

What it means

calculateDefaultExpBucketWidth computes the default log-scale bucket width for native histograms in the mantine-ui query page. When the last (rightmost) bucket's upper or lower bound parses as 0 — the [-0, 0] sentinel bucket Prometheus emits for underflow/overflow counts — it falls back to the second-to-last bucket. If that was the ONLY bucket, there is no interval to derive a width from, so it throws.

Source

Thrown at web/ui/mantine-ui/src/pages/query/HistogramHelpers.ts:14

// Calculates a default width of exponential histogram bucket ranges. If the last bucket is [0, 0],
// the width is calculated using the second to last bucket. returns error if the last bucket is [-0, 0],
export function calculateDefaultExpBucketWidth(
  last: [number, string, string, string],
  buckets: [number, string, string, string][]
): number {
  if (parseFloat(last[2]) === 0 || parseFloat(last[1]) === 0) {
    if (buckets.length > 1) {
      return Math.abs(
        Math.log(Math.abs(parseFloat(buckets[buckets.length - 2][2]))) -
          Math.log(Math.abs(parseFloat(buckets[buckets.length - 2][1])))
      );
    } else {
      throw new Error(
        "Only one bucket in histogram ([-0, 0]). Cannot calculate defaultExpBucketWidth."
      );
    }
  } else {
    return Math.abs(
      Math.log(Math.abs(parseFloat(last[2]))) -
        Math.log(Math.abs(parseFloat(last[1])))
    );
  }
}

// Finds the lowest positive value from the bucket ranges
// Returns 0 if no positive values are found or if there are no buckets.
export function findMinPositive(buckets: [number, string, string, string][]) {
  if (!buckets || buckets.length === 0) {
    return 0; // no buckets
  }
  for (let i = 0; i < buckets.length; i++) {

View on GitHub (pinned to 44d6a0e0b1)

Solutions

  1. Inspect the query result's buckets array to confirm the shape.
  2. Emit real histogram data (multiple bucket boundaries) from the source metric.
  3. If writing tests, use bucket arrays matching production shape (more than one finite bucket).
  4. Callers can catch this and fall back to a default width constant.

Example fix

// before
const width = calculateDefaultExpBucketWidth(buckets[buckets.length-1], buckets);

// after
try {
  const width = calculateDefaultExpBucketWidth(buckets[buckets.length-1], buckets);
} catch {
  const width = 1; // sensible default for degenerate single-bucket data
}
Defensive patterns

Strategy: try-catch

Validate before calling

const hasFiniteBucket = (b: [number, string, string, string][]) =>
  b.length > 1 || (parseFloat(b[0][1]) !== 0 && parseFloat(b[0][2]) !== 0);
if (!hasFiniteBucket(buckets)) skipHistogramPanel();

Type guard

function isDerivableHistogram(buckets: [number, string, string, string][]): boolean {
  if (buckets.length === 0) return false;
  const last = buckets[buckets.length - 1];
  return buckets.length > 1 || (parseFloat(last[1]) !== 0 && parseFloat(last[2]) !== 0);
}

Try / catch

try {
  width = calculateDefaultExpBucketWidth(last, buckets);
} catch (err) {
  if (err instanceof Error && err.message.includes('Only one bucket')) {
    width = 1; // fallback default
  } else throw err;
}

Prevention

When it happens

Trigger: A classic-histogram query result whose bucket array is exactly [['<ts>','-0','0','<count>']] — a single [-0,0] bucket. Real native histogram data always has multiple buckets, so this indicates degenerate or synthetic data.

Common situations: Test fixtures or mocked responses with a single zero-width bucket; scraped metrics exposing a histogram with no finite buckets; hand-crafted histogram samples during development.

Related errors


AI-assisted analysis of prometheus/prometheus@44d6a0e0b1 (2026-08-15). Data as JSON: /api/errors/80a3ba5106de371a. Report an issue: GitHub.