{"record":{"id":"626510b44848f489","repo":"pentaho/pentaho-kettle","slug":"key-already-added-key-key","errorCode":null,"errorMessage":"Key already added [key={key}]","messagePattern":"Key already added \\[key=(.+?)\\]","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/core/util/KeyValueSet.java","lineNumber":54,"sourceCode":"\n  /**\n   * Serial version UID.\n   */\n  private static final long serialVersionUID = 925133158112717153L;\n\n  private final Map<String, KeyValue<?>> entries = new TreeMap<String, KeyValue<?>>();\n\n  /**\n   * Add key value(s).\n   *\n   * @param keyValues\n   *          key values to add.\n   * @return this.\n   */\n  public KeyValueSet add( final KeyValue<?>... keyValues ) {\n    for ( KeyValue<?> keyValue : keyValues ) {\n      if ( this.entries.containsKey( keyValue.getKey() ) ) {\n        throw new IllegalArgumentException( \"Key already added [key=\" + keyValue.getKey() + \"]\" );\n      }\n      this.entries.put( keyValue.getKey(), keyValue );\n    }\n    return this;\n  }\n\n  /**\n   * {@inheritDoc}\n   *\n   * @see java.lang.Iterable#iterator()\n   */\n  public Iterator<KeyValue<?>> iterator() {\n    return this.keyValues().iterator();\n  }\n\n  /**\n   * @param key\n   *          the key.","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/core/util/KeyValueSet.java#L36-L72","documentation":"KeyValueSet.add() enforces unique keys within the set. If a KeyValue with an already-present key is added, it throws IllegalArgumentException('Key already added [key=...]'). KeyValueSet is a keyed collection, so duplicate keys would silently overwrite otherwise.","triggerScenarios":"Calling add(keyValue...) (or the fluent chain) with two KeyValue instances sharing the same key, including re-adding a key that was added in a previous add() call on the same set.","commonSituations":"Building a set from a list of parsed parameters where duplicates exist (repeated query/CLI parameters); loop code re-adding the same KeyValue; copy-paste of field definitions.","solutions":["Deduplicate the KeyValue array before calling add (e.g. via a LinkedHashMap keyed by getKey()).","Decide on overwrite semantics: remove the existing entry first or use put()/update if the API supports replacing.","Log or surface the duplicate source item instead of adding it blindly."],"exampleFix":"// before\nset.add(new KeyValue<>(\"retries\", 3));\nset.add(new KeyValue<>(\"retries\", 5)); // throws\n// after\nMap<String, KeyValue<?>> unique = new LinkedHashMap<>();\nfor (KeyValue<?> kv : keyValues) unique.putIfAbsent(kv.getKey(), kv);\nset.add(unique.values().toArray(new KeyValue<?>[0]));","handlingStrategy":"validation","validationCode":"Set<String> seen = new HashSet<>();\nfor (KeyValue<?> kv : keyValues) {\n  if (!seen.add(kv.getKey())) {\n    throw new IllegalArgumentException(\"Duplicate key in input: \" + kv.getKey());\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  set.add(keyValues);\n} catch (IllegalArgumentException e) {\n  // extract duplicate key from message and report source item, or deduplicate and retry\n}","preventionTips":["Deduplicate parsed parameter lists before building the KeyValueSet.","Decide explicitly between add (fail on duplicate) and replace semantics per use case.","Log duplicate sources (file line, request param) so users can fix the input."],"tags":["validation","duplicate-key","illegal-argument","collection"],"backgroundTag":"invalid-argument-value","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}