{"record":{"id":"2ac2d7733f80eb4e","repo":"apache/beam","slug":"approximateunique-perkey-needs-an-estimation-error-between-1","errorCode":null,"errorMessage":"ApproximateUnique.PerKey needs an estimation error between 1% (0.01) and 50% (0.5).","messagePattern":"ApproximateUnique\\.PerKey needs an estimation error between 1% \\(0\\.01\\) and 50% \\(0\\.5\\)\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/ApproximateUnique.java","lineNumber":255,"sourceCode":"     */\n    public PerKey(int sampleSize) {\n      if (sampleSize < 16) {\n        throw new IllegalArgumentException(\n            \"ApproximateUnique needs a \"\n                + \"sampleSize >= 16 for an estimation error <= 50%.  In general, \"\n                + \"the estimation error is about 2 / sqrt(sampleSize).\");\n      }\n\n      this.sampleSize = sampleSize;\n      this.maximumEstimationError = null;\n    }\n\n    /**\n     * @see ApproximateUnique#perKey(double)\n     */\n    public PerKey(double estimationError) {\n      if (estimationError < 0.01 || estimationError > 0.5) {\n        throw new IllegalArgumentException(\n            \"ApproximateUnique.PerKey needs an \"\n                + \"estimation error between 1% (0.01) and 50% (0.5).\");\n      }\n\n      this.sampleSize = sampleSizeFromEstimationError(estimationError);\n      this.maximumEstimationError = estimationError;\n    }\n\n    @Override\n    public PCollection<KV<K, Long>> expand(PCollection<KV<K, V>> input) {\n      Coder<KV<K, V>> inputCoder = input.getCoder();\n      if (!(inputCoder instanceof KvCoder)) {\n        throw new IllegalStateException(\n            \"ApproximateUnique.PerKey requires its input to use KvCoder\");\n      }\n      @SuppressWarnings(\"unchecked\")\n      final Coder<V> coder = ((KvCoder<K, V>) inputCoder).getValueCoder();\n","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/ApproximateUnique.java#L237-L273","documentation":"ApproximateUnique.PerKey estimates the number of distinct values per key, and its accuracy is controlled by an estimation error parameter. The library throws this IllegalArgumentException when the supplied estimation error is below 0.01 (1%) or above 0.5 (50%), because the underlying K-Minimum-Values algorithm only gives meaningful guarantees within that range. Values outside the range would silently produce misleading sample sizes or wasted work, so the constructor rejects them eagerly.","triggerScenarios":"Calling ApproximateUnique.perKey(double) or constructing new ApproximateUnique.PerKey<>(estimationError) with estimationError < 0.01 or estimationError > 0.5, including edge cases like 0.0 or 1.0.","commonSituations":"Developers copy a sampleSize-based setup and pass a percentage like 5 instead of 0.05, or ask for 0.1% precision (0.001) not realizing the algorithm cannot guarantee it.","solutions":["Express the error as a decimal fraction between 0.01 and 0.5 (e.g. 5% -> 0.05)","Clamp the user-supplied value before constructing: Math.max(0.01, Math.min(0.5, err))","If you need tighter than 1% accuracy, use exact counting (Count.perKey / Distinct) instead of ApproximateUnique"],"exampleFix":"// before\nPCollection<KV<K, Long>> counts = input.apply(ApproximateUnique.perKey(5.0));\n// after\nPCollection<KV<K, Long>> counts = input.apply(ApproximateUnique.perKey(0.05));","handlingStrategy":"validation","validationCode":"if (estimationError < 0.01 || estimationError > 0.5) {\n  throw new IllegalArgumentException(\"estimationError must be in [0.01, 0.5], got \" + estimationError);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always express the error as a decimal fraction (0.05 for 5%), never a percentage number","Clamp config-derived error values to [0.01, 0.5] before constructing PerKey","Use exact Count.perKey when sub-1% error is genuinely required"],"tags":["java","apache-beam","illegal-argument","pipeline-construction"],"backgroundTag":"value-out-of-range","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}