{"record":{"id":"ca56ebedd3484b97","repo":"apache/beam","slug":"expected-to-have-found-at-most-one-parameter-of-type-s-but","errorCode":null,"errorMessage":"Expected to have found at most one parameter of type %s but found %s.","messagePattern":"Expected to have found at most one parameter of type (.+?) but found (.+?)\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/reflect/DoFnSignatures.java","lineNumber":443,"sourceCode":"\n    /** Indicates whether the specified {@link Parameter} is known in this context. */\n    public boolean hasParameter(Class<? extends Parameter> type) {\n      return extraParameters.stream().anyMatch(Predicates.instanceOf(type)::apply);\n    }\n\n    /**\n     * Returns the specified {@link Parameter} if it is known in this context. Throws {@link\n     * IllegalStateException} if there is more than one instance of the parameter.\n     */\n    public <T extends Parameter> Optional<T> findParameter(Class<T> type) {\n      List<T> parameters = findParameters(type);\n      switch (parameters.size()) {\n        case 0:\n          return Optional.empty();\n        case 1:\n          return Optional.of(parameters.get(0));\n        default:\n          throw new IllegalStateException(\n              String.format(\n                  \"Expected to have found at most one parameter of type %s but found %s.\",\n                  type, parameters));\n      }\n    }\n\n    public <T extends Parameter> List<T> findParameters(Class<T> type) {\n      return (List<T>)\n          extraParameters.stream().filter(Predicates.instanceOf(type)).collect(Collectors.toList());\n    }\n\n    /** State parameters declared in this context, keyed by {@link StateId}. */\n    public Map<String, StateParameter> getStateParameters() {\n      return Collections.unmodifiableMap(stateParameters);\n    }\n\n    /** Timer parameters declared in this context, keyed by {@link TimerId}. */\n    public Map<String, TimerParameter> getTimerParameters() {","sourceCodeStart":425,"sourceCodeEnd":461,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/reflect/DoFnSignatures.java#L425-L461","documentation":"DoFnSignatures.findParameter collects all parameters of a given type from a DoFn method signature and expects at most one. Finding more than one means the DoFn method declares duplicate context parameters (e.g. two RestrictionTrackerParameters or two WatermarkEstimatorParameters) — by default unsupported and possibly ambiguous — so an IllegalStateException is thrown.","triggerScenarios":"Declaring a DoFn lifecycle method (e.g. @ProcessElement) with two parameters of the same special type, such as two RestrictionTracker parameters or two OnTimerContext parameters; this is flagged while building the DoFnSignature (findParameter is called by trackerT and watermarkEstimatorT signature checks).","commonSituations":"Copy-paste mistakes in a splittable DoFn method signature; refactoring that added a second tracker/estimator parameter; writing generic wrapper DoFns that accidentally duplicate parameter kinds.","solutions":["Remove the duplicate parameter so the method declares at most one of each type","If two trackers are genuinely needed, restructure the DoFn — Beam's signature model allows only one per method","Check the full validation error context in the IllegalStateException trace to find the offending method"],"exampleFix":"// before\n@ProcessElement\npublic void process(ProcessContext c, RestrictionTracker<R, Long> t1, RestrictionTracker<R, Long> t2) { ... }\n// after\n@ProcessElement\npublic void process(ProcessContext c, RestrictionTracker<R, Long> tracker) { ... }","handlingStrategy":"validation","validationCode":"long trackers = Arrays.stream(method.getParameterTypes())\n    .filter(t -> RestrictionTracker.class.isAssignableFrom(t)).count();\nif (trackers > 1) throw new IllegalArgumentException(\"At most one RestrictionTracker parameter allowed\");","typeGuard":"boolean hasUniqueSpecialParams(Method m) {\n  Set<Class<?>> seen = new HashSet<>();\n  for (Class<?> t : m.getParameterTypes()) {\n    if (!seen.add(t)) return false;\n  }\n  return true;\n}","tryCatchPattern":"try {\n  DoFnSignature sig = DoFnSignatures.getSignature(fn.getClass());\n} catch (IllegalStateException e) {\n  if (e.getMessage().contains(\"at most one parameter\")) {\n    throw new IllegalArgumentException(\"Fix duplicate DoFn method parameters\", e);\n  }\n  throw e;\n}","preventionTips":["Review splittable-DoFn method signatures for duplicated special parameters","Keep one parameter of each context type per lifecycle method","Run DoFn validation early (pipeline construction) to catch signature errors before runtime"],"tags":["java","apache-beam","dofn-signature","validation"],"backgroundTag":"invalid-argument-value","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"}