{"record":{"id":"cd530dd5b34d5057","repo":"prestodb/presto","slug":"invalid-function-argument-cd530d","errorCode":"INVALID_FUNCTION_ARGUMENT","errorMessage":"Percentile must be between 0 and 1","messagePattern":"Percentile must be between 0 and 1","errorType":"validation","errorClass":"PrestoException","httpStatus":null,"severity":"error","filePath":"presto-pinot-toolkit/src/main/java/com/facebook/presto/pinot/query/PinotQueryGenerator.java","lineNumber":439,"sourceCode":"            //     rsd = 1.106 / sqrt(2^(log2m))\n            // So:\n            //     log2m = 2 * log(1.106 / rsd) / log(2)\n            int log2m = (int) (2 * Math.log(1.106 / standardError) / Math.log(2));\n            if (log2m < 1) {\n                throw new PinotException(\n                        PINOT_UNSUPPORTED_EXPRESSION,\n                        Optional.empty(),\n                        format(\"Cannot handle approx_distinct, the log2m generated from error is %d from input %s (function %s)\", log2m, standardErrorString, aggregation));\n            }\n            return format(\"DISTINCTCOUNTHLL(%s, %d)\", selection, log2m);\n        }\n\n        private int getValidPercentile(String fraction)\n        {\n            try {\n                double percent = Double.parseDouble(fraction);\n                if (percent < 0 || percent > 1) {\n                    throw new PrestoException(INVALID_FUNCTION_ARGUMENT, \"Percentile must be between 0 and 1\");\n                }\n                percent = percent * 100.0;\n                if (percent == Math.floor(percent)) {\n                    return (int) percent;\n                }\n            }\n            catch (NumberFormatException ne) {\n                // Skip\n            }\n            return -1;\n        }\n\n        @Override\n        public PinotQueryGeneratorContext visitAggregation(AggregationNode node, PinotQueryGeneratorContext contextIn)\n        {\n            List<AggregationColumnNode> aggregationColumnNodes = computeAggregationNodes(node);\n\n            // Make two passes over the aggregationColumnNodes: In the first pass identify all the variables that will be used","sourceCodeStart":421,"sourceCodeEnd":457,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-pinot-toolkit/src/main/java/com/facebook/presto/pinot/query/PinotQueryGenerator.java#L421-L457","documentation":"getValidPercentile parses the percentile fraction string and validates it lies in [0, 1] before scaling to a percentage for Pinot's PERCENTILEEST aggregation. A fraction outside that range cannot be converted to a valid percentile, so the connector throws PrestoException with INVALID_FUNCTION_ARGUMENT.","triggerScenarios":"Pushing a percentile aggregation (e.g. percentile(x, 1.5) or percentile(x, -0.1)) down to Pinot where the fraction string parses to a double outside 0..1.","commonSituations":"Hand-written SQL passing 0-100 style percentile values (e.g. 95 instead of 0.95); programmatic query builders formatting the percentile with the wrong scale; dashboards configured with 'p95' mapped to 95.","solutions":["Pass the percentile as a fraction between 0 and 1, e.g. percentile(latency, 0.95) instead of percentile(latency, 95).","Normalize programmatic inputs before building the query: if the value > 1, divide by 100.","If the value should legitimately exceed 1, it is not a percentile; use a different aggregation."],"exampleFix":"// before\nSELECT percentile(latency, 95) FROM metrics;\n// after\nSELECT percentile(latency, 0.95) FROM metrics;","handlingStrategy":"validation","validationCode":"double p = Double.parseDouble(percentileInput);\nif (p < 0 || p > 1) {\n    throw new IllegalArgumentException(\"Percentile must be between 0 and 1, got: \" + p);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always express percentiles as fractions (0.95, not 95).","Normalize p>1 inputs by dividing by 100 in query builders.","Add unit tests for percentile argument formatting."],"tags":["pinot","pushdown","argument-validation","percentile"],"backgroundTag":"invalid-function-arguments","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}