{"record":{"id":"cb865ba7b3eb1a07","repo":"apache/beam","slug":"unable-to-infer-coder-for-keyt-s-specify-it-explicitly-using","errorCode":null,"errorMessage":"Unable to infer coder for KeyT (%s). Specify it explicitly using withOutputKeyCoder().","messagePattern":"Unable to infer coder for KeyT \\((.+?)\\)\\. Specify it explicitly using withOutputKeyCoder\\(\\)\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/Watch.java","lineNumber":810,"sourceCode":"                  + \"). Specify it explicitly using withOutputCoder().\");\n        }\n      }\n\n      Coder<KeyT> outputKeyCoder = getOutputKeyCoder();\n      SerializableFunction<OutputT, KeyT> outputKeyFn = getOutputKeyFn();\n      if (getOutputKeyFn() == null) {\n        // This by construction can happen only if OutputT == KeyT\n        outputKeyCoder = (Coder) outputCoder;\n        outputKeyFn = (SerializableFunction) SerializableFunctions.identity();\n      } else {\n        if (outputKeyCoder == null) {\n          // If a coder was not specified explicitly, infer it from the OutputT type parameter\n          // of the output key fn.\n          TypeDescriptor<KeyT> keyT = TypeDescriptors.outputOf(getOutputKeyFn());\n          try {\n            outputKeyCoder = input.getPipeline().getCoderRegistry().getCoder(keyT);\n          } catch (CannotProvideCoderException e) {\n            throw new RuntimeException(\n                \"Unable to infer coder for KeyT (\"\n                    + keyT\n                    + \"). Specify it explicitly using withOutputKeyCoder().\");\n          }\n        }\n        try {\n          outputKeyCoder.verifyDeterministic();\n        } catch (Coder.NonDeterministicException e) {\n          throw new IllegalArgumentException(\n              \"Key coder \" + outputKeyCoder + \" must be deterministic\");\n        }\n      }\n\n      PCollection<KV<InputT, List<TimestampedValue<OutputT>>>> polledPc =\n          input\n              .apply(\n                  ParDo.of(new WatchGrowthFn<>(this, outputCoder, outputKeyFn, outputKeyCoder))\n                      .withSideInputs(getPollFn().getRequirements().getSideInputs()))","sourceCodeStart":792,"sourceCodeEnd":828,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/Watch.java#L792-L828","documentation":"Watch.Growth must code the keys output by the output key function. If no key coder was provided with withOutputKeyCoder(), Beam infers KeyT from the function's type descriptor and asks the CoderRegistry; on CannotProvideCoderException it throws a RuntimeException instructing explicit specification. Common when KeyT is erased via a lambda or is an unregistered custom type.","triggerScenarios":"Applying Watch.growthOf(...).withOutputKeyFn(fn) where fn's KeyT type parameter cannot be resolved to a registered coder — lambda/anonymous function erasure, or a custom key type with no coder in the registry.","commonSituations":"Passing lambdas for output key functions so type descriptors are incomplete; custom key classes (e.g. protobuf types or POJOs) not registered with the CoderRegistry.","solutions":["Call .withOutputKeyCoder(coder) with an explicit Coder<KeyT>","Use a concrete named class (not a raw lambda) for the key function so KeyT resolves","Register the key type's coder via CoderRegistry.registerCoderForType","Switch to a standard key type (String, Long) with a built-in coder"],"exampleFix":"// before\nWatch.growthOf(pollFn).withOutputKeyFn(fn); // KeyT uninferrable\n// after\nWatch.growthOf(pollFn).withOutputKeyFn(fn).withOutputKeyCoder(StringUtf8Coder.of());","handlingStrategy":"validation","validationCode":"try {\n  pipeline.getCoderRegistry().getCoder(TypeDescriptors.outputOf(keyFn));\n} catch (CannotProvideCoderException e) {\n  growth = growth.withOutputKeyCoder(StringUtf8Coder.of());\n}","typeGuard":null,"tryCatchPattern":"try { pc = input.apply(growth); } catch (RuntimeException e) { if (e.getMessage().contains(\"Unable to infer coder for KeyT\")) { /* reapply with withOutputKeyCoder */ } }","preventionTips":["Specify withOutputKeyCoder() whenever using withOutputKeyFn()","Prefer concrete key types with built-in coders","Avoid raw lambda key functions in Watch configs"],"tags":["beam","coder","watch","type-inference"],"backgroundTag":"coder-inference-failed","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"}