{"record":{"id":"6f3d6e493f3512c5","repo":"apache/beam","slug":"tupletag-tag-corresponds-to-a-non-singleton-result","errorCode":null,"errorMessage":"TupleTag ${tag} corresponds to a non-singleton result","messagePattern":"TupleTag (.+?) corresponds to a non-singleton result","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/join/CoGbkResult.java","lineNumber":409,"sourceCode":"  private @Nullable <V> V innerGetOnly(\n      TupleTag<V> tag, @Nullable V defaultValue, boolean useDefault) {\n    int index = schema.getIndex(tag);\n    if (index < 0) {\n      throw new IllegalArgumentException(\"TupleTag \" + tag + \" is not in the schema\");\n    }\n    @SuppressWarnings(\"unchecked\")\n    Iterator<V> unions = (Iterator<V>) valueMap.get(index).iterator();\n    if (!unions.hasNext()) {\n      if (useDefault) {\n        return defaultValue;\n      } else {\n        throw new IllegalArgumentException(\n            \"TupleTag \" + tag + \" corresponds to an empty result, and no default was provided\");\n      }\n    }\n    V value = unions.next();\n    if (unions.hasNext()) {\n      throw new IllegalArgumentException(\n          \"TupleTag \" + tag + \" corresponds to a non-singleton result\");\n    }\n    return value;\n  }\n\n  /**\n   * A re-iterable that notifies an observer at every advance, and upon finishing, but only once\n   * across all copies.\n   *\n   * @param <T> The value type of the underlying iterable.\n   */\n  private static class ObservingReiterator<T> implements Reiterator<T> {\n\n    public interface Observer<T> {\n      /**\n       * Called exactly once, across all copies before advancing this iterator.\n       *\n       * <p>The iterator rather than the element is given so that the callee can perform a copy if","sourceCodeStart":391,"sourceCodeEnd":427,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/join/CoGbkResult.java#L391-L427","documentation":"getOnly() asserts the requested tag maps to exactly one value for the key. If more than one element exists in the iterable for that tag, the result is non-singleton and the method refuses to silently pick one.","triggerScenarios":"Calling getOnly(tag) on a key where the corresponding PCollection produced multiple records for that key in the CoGroupByKey output.","commonSituations":"Using getOnly() on many-to-many join results; one side of the join emits multiple values per key (e.g. repeated events per user id).","solutions":["Use get(tag) to obtain an Iterable and iterate all values","Ensure the PCollection for that tag is deduplicated per key (e.g. Distinct or combine) before joining","Use getAll(tag) when multiple values are legitimate"],"exampleFix":"// before\nV v = result.getOnly(tag); // throws if multiple\n// after\nfor (V v : result.getAll(tag)) { /* handle each */ }","handlingStrategy":"validation","validationCode":"if (result.getAll(tag).iterator().hasNext() && result.getAll(tag).spliterator().getExactSizeIfKnown() != 1) { /* handle multi-value */ }","typeGuard":null,"tryCatchPattern":"try { return result.getOnly(tag); } catch (IllegalArgumentException e) { /* fall back to iterable handling */ }","preventionTips":["Use get()/getAll() unless you guarantee singleton cardinality","Deduplicate inputs per key before joining","Combine values per key before CoGroupByKey"],"tags":["beam","cogbkresult","getonly","non-singleton"],"backgroundTag":"unsupported-operation","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}