{"id":"4e207bce01101240","repo":"apache/kafka","slug":"linear-bucket-sizing-requires-min-to-be-0-0","errorCode":null,"errorMessage":"Linear bucket sizing requires min to be 0.0.","messagePattern":"Linear bucket sizing requires min to be 0\\.0\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/metrics/stats/Percentiles.java","lineNumber":64,"sourceCode":"    private final BinScheme binScheme;\n    private final double min;\n    private final double max;\n\n    public Percentiles(int sizeInBytes, double max, BucketSizing bucketing, Percentile... percentiles) {\n        this(sizeInBytes, 0.0, max, bucketing, percentiles);\n    }\n\n    public Percentiles(int sizeInBytes, double min, double max, BucketSizing bucketing, Percentile... percentiles) {\n        super(0.0);\n        this.percentiles = percentiles;\n        this.buckets = sizeInBytes / 4;\n        this.min = min;\n        this.max = max;\n        if (bucketing == BucketSizing.CONSTANT) {\n            this.binScheme = new ConstantBinScheme(buckets, min, max);\n        } else if (bucketing == BucketSizing.LINEAR) {\n            if (min != 0.0d)\n                throw new IllegalArgumentException(\"Linear bucket sizing requires min to be 0.0.\");\n            this.binScheme = new LinearBinScheme(buckets, max);\n        } else {\n            throw new IllegalArgumentException(\"Unknown bucket type: \" + bucketing);\n        }\n    }\n\n    @Override\n    public List<NamedMeasurable> stats() {\n        List<NamedMeasurable> ms = new ArrayList<>(this.percentiles.length);\n        for (Percentile percentile : this.percentiles) {\n            final double pct = percentile.percentile();\n            ms.add(new NamedMeasurable(\n                percentile.name(),\n                (config, now) -> value(config, now, pct / 100.0))\n            );\n        }\n        return ms;\n    }","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/metrics/stats/Percentiles.java#L46-L82","documentation":"Thrown by the Percentiles constructor when `BucketSizing.LINEAR` is selected but `min` is not exactly 0.0. LinearBinScheme is mathematically defined only for a domain starting at zero (its `toBin` inversion uses `sqrt(1 + 8x/scale)` assuming x >= 0 from 0). Allowing a non-zero min would shift the recorded values out of the scheme's valid range and produce wrong percentiles, so Kafka rejects it.","triggerScenarios":"Calling `new Percentiles(sizeInBytes, min, max, BucketSizing.LINEAR, percentiles...)` with `min != 0.0`. The convenience constructor `Percentiles(sizeInBytes, max, bucketing, percentiles...)` defaults min to 0.0 and is safe.","commonSituations":"A developer wants percentile latency between, say, 10ms and 1000ms and tries to set min=10 with LINEAR bucketing. Mixing up the 4-arg and 5-arg Percentiles constructors. Copying a CONSTANT-bucketing config (which allows arbitrary min) and flipping the enum to LINEAR without zeroing min.","solutions":["Set `min = 0.0` when using BucketSizing.LINEAR (use the 4-arg constructor which does this for you).","If you need a non-zero min, switch to `BucketSizing.CONSTANT`.","Pre-process values by subtracting the desired min and use CONSTANT binning instead."],"exampleFix":"// before\nnew Percentiles(4096, 10.0, 1000.0, BucketSizing.LINEAR, p50, p99);\n\n// after (option A: keep LINEAR, min=0)\nnew Percentiles(4096, 0.0, 1000.0, BucketSizing.LINEAR, p50, p99);\n// after (option B: keep min=10, switch to CONSTANT)\nnew Percentiles(4096, 10.0, 1000.0, BucketSizing.CONSTANT, p50, p99);","handlingStrategy":"validation","validationCode":"if (bucketing == Percentiles.BucketSizing.LINEAR && Double.compare(min, 0.0d) != 0) {\n    throw new IllegalArgumentException(\n        \"Percentiles LINEAR bucketing requires min == 0.0, got \" + min);\n}\nnew Percentiles(sizeInBytes, min, max, bucketing, percentiles);","typeGuard":null,"tryCatchPattern":"try {\n    new Percentiles(sizeInBytes, min, max, bucketing, percentiles);\n} catch (IllegalArgumentException e) {\n    // \"Linear bucket sizing requires min to be 0.0.\"\n    if (bucketing == Percentiles.BucketSizing.LINEAR) {\n        new Percentiles(sizeInBytes, 0.0, max, bucketing, percentiles);\n    } else {\n        throw e;\n    }\n}","preventionTips":["For LINEAR sizing, use the 4-arg constructor with min=0.0 or the 3-arg Percentiles(sizeInBytes, max, LINEAR, ...) which forces min=0.","Reserve nonzero min for CONSTANT bucketing only.","Encode the (bucketing, min) compatibility rule in a factory helper so call sites cannot pair LINEAR with a nonzero min."],"tags":["metrics","percentiles","linear-binning","configuration","validation","java"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}