apache/skywalking · error · IllegalArgumentException

Incompatible BucketedValues

Error message

Incompatible BucketedValues [{}] for current HistogramFunction[{}]

What it means

HistogramFunction.accept() accumulates into a DataTable keyed by bucket names. Once the dataset is non-empty, an incoming BucketedValues must be isCompatible() with the existing dataset — same bucket key set — otherwise the accumulation would mix incommensurable buckets and the throw happens. The message embeds both the incoming value and the current dataset for diagnosis.

Solutions

  1. Align bucket configuration across every producer of the metric (same valueBuckets / bucket list, including infinity buckets)
  2. If buckets legitimately changed, use a new metric name for the new bucket set, or restart OAP so in-memory datasets reset (persisted data still needs migration/drop)
  3. Standardize bucket templates in shared config so all senders derive buckets identically

Example fix

# before — two rules emit metric with different buckets
rule_a: metric m1 buckets: 10,50,100
rule_b: metric m1 buckets: 20,40,60

# after
rule_a: metric m1 buckets: 10,50,100
rule_b: metric m1_v2 buckets: 20,40,60
Defensive patterns

Strategy: try-catch

Validate before calling

// producer-side: derive buckets from ONE shared config so every emission matches
long[] buckets = SharedBucketConfig.bucketsFor(metricName); // single source of truth
long[] values = new long[buckets.length];
// ... fill values ...
histogramFunction.accept(entity, new BucketedValues(buckets, values));

Try / catch

try {
    histogramMetric.accept(entity, bucketedValues);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("Incompatible BucketedValues")) {
        log.error("Bucket config drift on {} — align producers or version the metric name", metricName, e);
        return; // drop the sample rather than kill the stream worker
    }
    throw e;
}

Prevention

When it happens

Trigger: The same histogram metric name receives BucketedValues with different bucket sets: e.g. two agents/rules with different bucket configs report the same metric; a MAL rule's buckets were changed and the new values arrive while the old persisted/aggregated dataset is still in memory; one producer includes the Long.MIN_VALUE infinity-negative sentinel bucket and another does not.

Common situations: Rolling out a new agent version with different default buckets while OAP keeps aggregating the same metric; multi-tenant setups where different teams configure the same metric name with different valueBuckets; editing MAL otel-rules bucket lists at runtime.

Related errors


AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14). Data as JSON: /api/errors/2e8c76906829cda9. Report an issue: GitHub.

Appendix: source

Thrown at oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/HistogramFunction.java:68

    public static final String DATASET = "dataset";

    @Setter
    @Getter
    @ElasticSearch.EnableDocValues
    @Column(name = ENTITY_ID, length = 512)
    @BanyanDB.SeriesID(index = 0)
    private String entityId;
    @Getter
    @Setter
    @Column(name = DATASET, dataType = Column.ValueDataType.HISTOGRAM, storageOnly = true, defaultValue = 0)
    @BanyanDB.MeasureField
    private DataTable dataset = new DataTable(30);

    @Override
    public void accept(final MeterEntity entity, final BucketedValues value) {
        if (dataset.size() > 0) {
            if (!value.isCompatible(dataset)) {
                throw new IllegalArgumentException(
                    "Incompatible BucketedValues [" + value + "] for current HistogramFunction[" + dataset + "]");
            }
        }

        this.entityId = entity.id();

        final long[] values = value.getValues();
        for (int i = 0; i < values.length; i++) {
            final long bucket = value.getBuckets()[i];
            String bucketName = bucket == Long.MIN_VALUE ? Bucket.INFINITE_NEGATIVE : String.valueOf(bucket);
            final long bucketValue = values[i];
            dataset.valueAccumulation(bucketName, bucketValue);
        }
    }

    @Override
    public boolean combine(final Metrics metrics) {
        HistogramFunction histogram = (HistogramFunction) metrics;

View on GitHub (pinned to 102af09b4a)