{"record":{"id":"3eaea31a4eeea4c1","repo":"apache/beam","slug":"cannot-return-null-keycoder","errorCode":null,"errorMessage":"cannot return null keyCoder","messagePattern":"cannot return null keyCoder","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/join/KeyedPCollectionTuple.java","lineNumber":141,"sourceCode":"   * Expands the component {@link PCollection PCollections}, stripping off any tag-specific\n   * information.\n   */\n  @Override\n  public Map<TupleTag<?>, PValue> expand() {\n    ImmutableMap.Builder<TupleTag<?>, PValue> retval = ImmutableMap.builder();\n    for (TaggedKeyedPCollection<K, ?> taggedPCollection : keyedCollections) {\n      retval.put(taggedPCollection.tupleTag, taggedPCollection.pCollection);\n    }\n    return retval.build();\n  }\n\n  /**\n   * Returns the key {@link Coder} for all {@link PCollection PCollections} in this {@link\n   * KeyedPCollectionTuple}.\n   */\n  public Coder<K> getKeyCoder() {\n    if (keyCoder == null) {\n      throw new IllegalStateException(\"cannot return null keyCoder\");\n    }\n    return keyCoder;\n  }\n\n  /** Returns the {@link CoGbkResultSchema} associated with this {@link KeyedPCollectionTuple}. */\n  public CoGbkResultSchema getCoGbkResultSchema() {\n    return schema;\n  }\n\n  @Override\n  public Pipeline getPipeline() {\n    return pipeline;\n  }\n\n  private static <K, V> Coder<K> getKeyCoder(PCollection<KV<K, V>> pc) {\n    // TODO: This should already have run coder inference for output, but may not have been consumed\n    // as input yet (and won't be fully specified); This is fine\n","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/join/KeyedPCollectionTuple.java#L123-L159","documentation":"getKeyCoder() on a KeyedPCollectionTuple returns the cached keyCoder, but if the tuple was constructed without one (null) and no input has forced inference yet, it refuses to return null and throws an IllegalStateException.","triggerScenarios":"Calling getKeyCoder() (or keyCoder-through paths) on a KeyedPCollectionTuple whose keyCoder field is null because no PCollection coder was consulted yet, e.g. on an empty or not-fully-built tuple.","commonSituations":"Inspecting the key coder before applying the transform; a zero-input tuple passed around for testing; framework code reading keyCoder on a partially constructed tuple.","solutions":["Ensure at least one input PCollection with a KvCoder was added before calling getKeyCoder()","Construct the KeyedPCollectionTuple with an explicit key coder (e.g. KeyedPCollectionTuple.of creates it from the first input)","Guard the call with keyCoder null-check via getCoGbkResultSchema/getPipeline introspection instead"],"exampleFix":"// before\nCoder<K> kCoder = tuple.getKeyCoder(); // NPE-style state error if empty\n// after\nif (!tuple.isEmpty()) {\n  Coder<K> kCoder = tuple.getKeyCoder();\n}","handlingStrategy":"try-catch","validationCode":"if (tuple.isEmpty()) { throw new IllegalStateException(\"Cannot get key coder from empty KeyedPCollectionTuple\"); }","typeGuard":null,"tryCatchPattern":"try { return tuple.getKeyCoder(); } catch (IllegalStateException e) { return inferFromFirstInput(tuple); }","preventionTips":["Ensure at least one input exists before querying key coder","Provide key coder explicitly at tuple construction","Avoid calling getKeyCoder during pipeline construction before inference completes"],"tags":["beam","keyedpcollectiontuple","keycoder","illegal-state"],"backgroundTag":"null-argument","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}