{"record":{"id":"ceb82bbd157faa5c","repo":"pentaho/pentaho-kettle","slug":"key-must-not-be","errorCode":null,"errorMessage":"Key must not be  '_'","messagePattern":"Key must not be  '_'","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/core/util/KeyValue.java","lineNumber":99,"sourceCode":"   * @param lowerKey\n   *          key to test.\n   * @throws IllegalArgumentException\n   *           if key is invalid.\n   */\n  public static final void assertKey( final String lowerKey ) throws IllegalArgumentException {\n    Assert.assertNotEmpty( lowerKey, \"Key cannot be null or empty\" );\n    if ( !StringUtils.containsOnly( lowerKey, VALID_KEY_CHARS ) ) {\n      throw new IllegalArgumentException( \"Key contains invalid characters [validKeyCharacters=\"\n        + VALID_KEY_CHARS + \"]\" );\n    }\n    if ( lowerKey.charAt( 0 ) == '-' ) {\n      throw new IllegalArgumentException( \"Key must not start with '-'\" );\n    }\n    if ( lowerKey.endsWith( \"-\" ) ) {\n      throw new IllegalArgumentException( \"Key must not end with '-'\" );\n    }\n    if ( \"_\".equals( lowerKey ) ) {\n      throw new IllegalArgumentException( \"Key must not be  '_'\" );\n    }\n  }\n\n  /**\n   * @return the key, never null.\n   */\n  public String getKey() {\n    return this.key;\n  }\n\n  /**\n   * @return the value\n   */\n  public T getValue() {\n    return this.value;\n  }\n\n  /**","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/core/util/KeyValue.java#L81-L117","documentation":"KeyValue.assertKey() rejects the single-character key '_' because it is reserved/meaningless as a named value key and can collide with placeholder conventions. It throws IllegalArgumentException('Key must not be  \\'_\\'').","triggerScenarios":"Constructing a KeyValue with key exactly \"_\", e.g. when a placeholder token or an anonymous/blank key collapses to a single underscore.","commonSituations":"Template or aggregation code that uses '_' as a throwaway name; sanitizing an invalid key by replacing every character with '_' leaves a bare underscore.","solutions":["Choose a meaningful key name instead of the underscore placeholder.","After sanitizing, check for the degenerate all-underscores result and substitute a real name.","Guard your key-building function to reject or rename '_' before constructing KeyValue."],"exampleFix":"// before\nnew KeyValue<>(\"_\", value); // placeholder\n// after\nString key = sanitized.isEmpty() || \"_\".equals(sanitized) ? \"unnamed-field\" : sanitized;\nnew KeyValue<>(key, value);","handlingStrategy":"validation","validationCode":"if (\"_\".equals(key)) {\n  throw new IllegalArgumentException(\"Key '_' is reserved; use a meaningful name\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  new KeyValue<>(key, value);\n} catch (IllegalArgumentException e) {\n  if (\"_\".equals(key)) key = \"unnamed\"; // replace placeholder before retry\n}","preventionTips":["Reject all-underscore keys after sanitization — they indicate the original name was wholly invalid.","Use named placeholder conventions (e.g. 'unnamed', 'field-1') rather than '_'.","Validate key names at the point of key construction, not deep in the pipeline."],"tags":["validation","key-format","illegal-argument"],"backgroundTag":"invalid-identifier-format","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"}