pentaho/pentaho-kettle · error · IllegalArgumentException

Key must not be '_'

Error message

Key must not be  '_'

What it means

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 \'_\'').

Solutions

  1. Choose a meaningful key name instead of the underscore placeholder.
  2. After sanitizing, check for the degenerate all-underscores result and substitute a real name.
  3. Guard your key-building function to reject or rename '_' before constructing KeyValue.

Example fix

// before
new KeyValue<>("_", value); // placeholder
// after
String key = sanitized.isEmpty() || "_".equals(sanitized) ? "unnamed-field" : sanitized;
new KeyValue<>(key, value);
Defensive patterns

Strategy: validation

Validate before calling

if ("_".equals(key)) {
  throw new IllegalArgumentException("Key '_' is reserved; use a meaningful name");
}

Try / catch

try {
  new KeyValue<>(key, value);
} catch (IllegalArgumentException e) {
  if ("_".equals(key)) key = "unnamed"; // replace placeholder before retry
}

Prevention

When it happens

Trigger: Constructing a KeyValue with key exactly "_", e.g. when a placeholder token or an anonymous/blank key collapses to a single underscore.

Common situations: Template or aggregation code that uses '_' as a throwaway name; sanitizing an invalid key by replacing every character with '_' leaves a bare underscore.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/ceb82bbd157faa5c. Report an issue: GitHub.

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/core/util/KeyValue.java:99

   * @param lowerKey
   *          key to test.
   * @throws IllegalArgumentException
   *           if key is invalid.
   */
  public static final void assertKey( final String lowerKey ) throws IllegalArgumentException {
    Assert.assertNotEmpty( lowerKey, "Key cannot be null or empty" );
    if ( !StringUtils.containsOnly( lowerKey, VALID_KEY_CHARS ) ) {
      throw new IllegalArgumentException( "Key contains invalid characters [validKeyCharacters="
        + VALID_KEY_CHARS + "]" );
    }
    if ( lowerKey.charAt( 0 ) == '-' ) {
      throw new IllegalArgumentException( "Key must not start with '-'" );
    }
    if ( lowerKey.endsWith( "-" ) ) {
      throw new IllegalArgumentException( "Key must not end with '-'" );
    }
    if ( "_".equals( lowerKey ) ) {
      throw new IllegalArgumentException( "Key must not be  '_'" );
    }
  }

  /**
   * @return the key, never null.
   */
  public String getKey() {
    return this.key;
  }

  /**
   * @return the value
   */
  public T getValue() {
    return this.value;
  }

  /**

View on GitHub (pinned to f3058517a1)