elastic/elasticsearch · error · IllegalArgumentException

Can't use ${scaleFunction} as scale with ${this}

Error message

Can't use ${scaleFunction} as scale with ${this}

What it means

TDigest.setScaleFunction rejects any ScaleFunction whose toString() ends with NO_NORM. Un-normalised scale functions are mathematically incompatible with how this t-digest lays out centroids, so the configuration is rejected rather than producing silently wrong quantiles.

Source

Thrown at libs/tdigest/src/main/java/org/elasticsearch/tdigest/TDigest.java:163

    public abstract double quantile(double q);

    /**
     * Returns the current compression factor.
     *
     * @return The compression factor originally used to set up the TDigest.
     */
    public abstract double compression();

    /**
     * Returns the number of bytes required to encode this TDigest using #asBytes().
     *
     * @return The number of bytes required.
     */
    public abstract int byteSize();

    public void setScaleFunction(ScaleFunction scaleFunction) {
        if (scaleFunction.toString().endsWith("NO_NORM")) {
            throw new IllegalArgumentException(String.format(Locale.ROOT, "Can't use %s as scale with %s", scaleFunction, this.getClass()));
        }
        this.scale = scaleFunction;
    }

    /**
     * Add all of the centroids of another digest to this one.
     *
     * @param other The other digest
     */
    public abstract void add(TDigestReadView other);

    /**
     * Prepare internal structure for loading the requested number of samples.
     * @param size number of samples to be loaded
     */
    public void reserve(long size) {}

    public double getMin() {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Use the normalised counterpart of the scale function (the name without the NO_NORM suffix)
  2. If you specifically need a NO_NORM scale, switch to a digest implementation that supports it instead of forcing it here
  3. Validate the ScaleFunction name before assignment

Example fix

// before
digest.setScaleFunction(ScaleFunction.K_0_NO_NORM);
// after
digest.setScaleFunction(ScaleFunction.K_0);
Defensive patterns

Strategy: validation

Validate before calling

String name = scaleFunction.toString();
if (name.endsWith("NO_NORM")) {
    throw new IllegalArgumentException("NO_NORM scales are not supported by TDigest: " + name);
}
digest.setScaleFunction(scaleFunction);

Type guard

static boolean isSupportedScale(ScaleFunction f) {
    return f != null && !f.toString().endsWith("NO_NORM");
}

Try / catch

try { digest.setScaleFunction(fn); }
catch (IllegalArgumentException e) { /* pick the normalised variant */ }

Prevention

When it happens

Trigger: Calling tdigest.setScaleFunction(fn) where fn.toString() ends in NO_NORM (e.g. k_0_NO_NORM, k_2_NO_NORM, normalAsin_NO_NORM). The check is string-based on the function name suffix.

Common situations: Programmatically tuning the compression profile and selecting a NO_NORM variant by mistake; copy-pasting scale configuration from a different t-digest implementation that allows un-normalised scales; serialising/deserialising a digest and re-applying the wrong scale on restore.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/74d86834c3921808. Report an issue: GitHub.