{"record":{"id":"59025ae58d5ad9c8","repo":"risingwavelabs/risingwave","slug":"relative-error-must-be-in-the-range-0-1-got","errorCode":null,"errorMessage":"relative_error must be in the range (0, 1), got {}","messagePattern":"relative_error must be in the range \\(0, 1\\), got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/expr/impl/src/aggregate/approx_percentile.rs","lineNumber":43,"sourceCode":"use risingwave_expr::aggregate::{AggCall, AggStateDyn, AggregateFunction, AggregateState};\nuse risingwave_expr::{Result, build_aggregate};\n\n/// TODO(kwannoel): for single phase agg, we can actually support `UDDSketch`.\n/// For two phase agg, we still use `DDSketch`.\n/// Then we also need to store the `relative_error` of the sketch, so we can report it\n/// in an internal table, if it changes.\n#[build_aggregate(\"approx_percentile(float8) -> float8\", state = \"bytea\")]\nfn build(agg: &AggCall) -> Result<Box<dyn AggregateFunction>> {\n    let quantile = agg.direct_args[0]\n        .literal()\n        .map(|x| (*x.as_float64()).into())\n        .unwrap();\n    let relative_error: f64 = agg.direct_args[1]\n        .literal()\n        .map(|x| (*x.as_float64()).into())\n        .unwrap();\n    if relative_error <= 0.0 || relative_error >= 1.0 {\n        bail!(\n            \"relative_error must be in the range (0, 1), got {}\",\n            relative_error\n        )\n    }\n    let base = (1.0 + relative_error) / (1.0 - relative_error);\n    Ok(Box::new(ApproxPercentile { quantile, base }))\n}\n\npub struct ApproxPercentile {\n    quantile: f64,\n    base: f64,\n}\n\ntype BucketCount = u64;\ntype BucketId = i32;\ntype Count = u64;\n\n#[derive(Debug, Default)]","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/expr/impl/src/aggregate/approx_percentile.rs#L25-L61","documentation":"`approx_percentile` takes the relative error as a constant DIRECT argument of the aggregate call. The builder requires it to be strictly between 0 and 1 (exclusive) because it is used to compute ratio `base = (1+e)/(1-e)`, which is undefined or degenerate outside that range.","triggerScenarios":"`approx_percentile(x, q, e)` called with e <= 0.0 or e >= 1.0, e.g. `approx_percentile(latency, 0.95, 1.0)` or `approx_percentile(latency, 0.95, 0)`, at materialized-view/aggregate build time.","commonSituations":"Confusing relative error with percentile (passing 0.95 as error); passing 0 expecting 'exact'; unit confusion (passing 100 for percent instead of 0.01-0.99).","solutions":["Pass a relative error strictly between 0 and 1, e.g. 0.01 for ~1% error.","Check argument order: quantile first, relative error second, both as literals.","Remember the error is a fraction, not a percentage: use 0.05 not 5."],"exampleFix":"// before\nSELECT approx_percentile(latency, 0.95, 1.0) FROM t;\n// after\nSELECT approx_percentile(latency, 0.95, 0.01) FROM t;","handlingStrategy":"validation","validationCode":"-- verify the error argument before running the query\n-- in application code (JS example):\nif (!(relErr > 0 && relErr < 1)) throw new Error('relative_error must be in (0,1)');","typeGuard":null,"tryCatchPattern":"match approx_percentile_build(...) {\n    Err(e) if e.to_string().contains(\"relative_error\") => {\n        // fall back to a default error like 0.01\n    }\n    other => other?,\n}","preventionTips":["Always pass relative error as a fraction strictly between 0 and 1.","Never confuse quantile (0..1) with relative error (0..1).","Use literals, not expressions, for the DIRECT arguments."],"tags":["rust","sql","aggregate","approx-percentile"],"backgroundTag":"invalid-argument-value","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}