{"record":{"id":"f2009e18a71f59b8","repo":"risingwavelabs/risingwave","slug":"relative-error-does-not-satisfy-0-0-relative","errorCode":null,"errorMessage":"relative_error={} does not satisfy 0.0 < relative_error < 1.0","messagePattern":"relative_error=(.+?) does not satisfy 0\\.0 < relative_error < 1\\.0","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/frontend/src/binder/expr/function/aggregate.rs","lineNumber":166,"sourceCode":"                            kind\n                        ))\n                    })?;\n                }\n            }\n            (AggType::Builtin(PbAggKind::Mode), 0, [_arg]) => {}\n            (AggType::Builtin(PbAggKind::ApproxPercentile), 1..=2, [_percentile_col]) => {\n                let percentile = &mut direct_args[0];\n                decimal_to_float64(percentile, kind)?;\n                match direct_args.len() {\n                    2 => {\n                        let relative_error = &mut direct_args[1];\n                        decimal_to_float64(relative_error, kind)?;\n                        if let Some(relative_error) = relative_error.as_literal()\n                            && let Some(relative_error) = relative_error.get_data()\n                        {\n                            let relative_error = relative_error.as_float64().0;\n                            if relative_error <= 0.0 || relative_error >= 1.0 {\n                                bail!(\n                                    \"relative_error={} does not satisfy 0.0 < relative_error < 1.0\",\n                                    relative_error,\n                                )\n                            }\n                        }\n                    }\n                    1 => {\n                        let relative_error: ExprImpl = Literal::new(\n                            ScalarImpl::Float64(0.01.into()).into(),\n                            DataType::Float64,\n                        )\n                        .into();\n                        direct_args.push(relative_error);\n                    }\n                    _ => {\n                        return Err(ErrorCode::InvalidInputSyntax(\n                            \"invalid direct args for approx_percentile aggregation\".to_owned(),\n                        )","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/frontend/src/binder/expr/function/aggregate.rs#L148-L184","documentation":"Thrown when binding an ordered-set aggregate (e.g. `approx_percentile` with a relative_error argument). The binder parses the second argument as a literal float and validates that it lies strictly between 0.0 and 1.0; values <= 0.0 or >= 1.0 are rejected with this error.","triggerScenarios":"Executing an ordered-set aggregate like `approx_percentile(x, 1.0)`, `approx_percentile(x, 0.0)`, or any negative/out-of-range literal as the relative_error argument; also non-literal arguments are skipped by this check (only literals are validated here).","commonSituations":"Users writing percentile accuracy as a percentage (e.g. 5 meaning 5%) instead of a fraction (0.05); copy-pasted SQL from other engines with different argument semantics; typos like `1` instead of `0.1`.","solutions":["Pass a relative_error literal strictly between 0 and 1, e.g. `approx_percentile(col, 0.01)`.","Convert percentage values by dividing by 100 (5% -> 0.05).","Check the function signature documentation for the exact ordered-set aggregate argument order."],"exampleFix":"// before\nSELECT approx_percentile(value, 1.0) FROM t;\n// after\nSELECT approx_percentile(value, 0.01) FROM t;","handlingStrategy":"validation","validationCode":"if !(relative_error > 0.0 && relative_error < 1.0) {\n  throw new Error(\"relative_error must be strictly between 0 and 1\");\n}","typeGuard":"function isValidRelativeError(v: number): boolean { return Number.isFinite(v) && v > 0 && v < 1; }","tryCatchPattern":"try {\n  await client.query(\"SELECT approx_percentile(v, $1) FROM t\", [rel]);\n} catch (e) {\n  if (String(e.message).includes(\"does not satisfy 0.0 < relative_error < 1.0\")) {\n    // clamp/correct the argument and retry\n  } else throw e;\n}","preventionTips":["Express accuracy as a fraction, not a percentage (5% -> 0.05)","Validate the literal client-side before issuing the SQL","Remember only literal arguments are validated; avoid dynamic expressions where possible"],"tags":["sql","aggregate","validation","frontend"],"backgroundTag":"value-out-of-range","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"}