{"record":{"id":"33b0c5ab0ad557e9","repo":"elastic/elasticsearch","slug":"invalid-value-x","errorCode":null,"errorMessage":"Invalid value: ${x}","messagePattern":"Invalid value: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"libs/tdigest/src/main/java/org/elasticsearch/tdigest/TDigest.java","lineNumber":113,"sourceCode":"     * Adds a sample to a histogram.\n     *\n     * @param x The value to add.\n     * @param w The weight of this point.\n     */\n    public abstract void add(double x, long w);\n\n    /**\n     * Add a single sample to this TDigest.\n     *\n     * @param x The data value to add\n     */\n    public final void add(double x) {\n        add(x, 1);\n    }\n\n    static void checkValue(double x) {\n        if (Double.isNaN(x) || Double.isInfinite(x)) {\n            throw new IllegalArgumentException(\"Invalid value: \" + x);\n        }\n    }\n\n    /**\n     * Re-examines a t-digest to determine whether some centroids are redundant.  If your data are\n     * perversely ordered, this may be a good idea.  Even if not, this may save 20% or so in space.\n     *\n     * The cost is roughly the same as adding as many data points as there are centroids.  This\n     * is typically &lt; 10 * compression, but could be as high as 100 * compression.\n     *\n     * This is a destructive operation that is not thread-safe.\n     */\n    public abstract void compress();\n\n    /**\n     * Returns the fraction of all points added which are &le; x. Points\n     * that are exactly equal get half credit (i.e. we use the mid-point\n     * rule)","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/tdigest/src/main/java/org/elasticsearch/tdigest/TDigest.java#L95-L131","documentation":"TDigest.checkValue rejects NaN and infinite doubles before adding them as samples. The t-digest algorithm cannot represent an unrepresentable numeric value as a centroid, so add()/add(x,1) calls checkValue and throws IllegalArgumentException for NaN, POSITIVE_INFINITY, or NEGATIVE_INFINITY.","triggerScenarios":"Calling tdigest.add(x) or tdigest.add(x, w) where x is Double.NaN, Double.POSITIVE_INFINITY, or Double.NEGATIVE_INFINITY. Also reached via add(TDigestReadView) if the other digest contains a bad mean.","commonSituations":"Feeding metric values from a source that emits NaN for missing data (division by zero upstream); log-derived doubles that overflow to infinity; sensor readings with sentinel NaN values; aggregations that produce infinity from max/min of unbounded streams.","solutions":["Filter out non-finite values before adding: if (Double.isFinite(x)) digest.add(x)","Treat NaN/Infinity as missing data and skip the sample, or replace with a defined sentinel the algorithm tolerates","Audit upstream calculations for division by zero and overflow"],"exampleFix":"// before\ndigest.add(value); // value may be NaN/Infinity\n// after\nif (Double.isFinite(value)) {\n    digest.add(value);\n}","handlingStrategy":"type-guard","validationCode":"if (!Double.isFinite(x)) {\n    // skip or record as missing\n    return;\n}\ndigest.add(x);","typeGuard":"static boolean isAddable(double x) { return Double.isFinite(x); }","tryCatchPattern":"try { digest.add(x); }\ncatch (IllegalArgumentException e) { /* drop sample */ }","preventionTips":["Filter non-finite values at ingestion","Treat NaN as missing data, not as a sample","Sanitise sensor/log inputs before aggregation"],"tags":["tdigest","nan","infinity","input-validation"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}