pentaho/pentaho-kettle · error · KettleValueException

<toString()> : couldn't convert Number to String

Error message

<toString()> : couldn't convert Number to String 

What it means

Thrown by ValueMetaBase's Number-to-String conversion when DecimalFormat.format(number) throws for any reason. It wraps the underlying exception and names the value meta, meaning the numeric value could not be formatted with the current format mask/locale settings.

Solutions

  1. Check the conversion mask is a valid DecimalFormat pattern for the value
  2. Handle NaN/Infinity values before conversion (substitute null or a string)
  3. Normalize the conversion mask so it matches storageMetadata or clear it
  4. Catch KettleValueException and fall back to String.valueOf(number)

Example fix

// before
valueMeta.setConversionMask("###,##0.00;;"); // invalid pattern
// after
valueMeta.setConversionMask("#,##0.00");
Defensive patterns

Strategy: try-catch

Validate before calling

static boolean isValidDecimalMask(String mask, Locale locale) {
  try { new java.text.DecimalFormat(mask, new java.text.DecimalFormatSymbols(locale)); return true; }
  catch (IllegalArgumentException e) { return false; }
}

Try / catch

try {
  String s = valueMeta.getString(numberObject);
} catch (KettleValueException e) {
  log.error("Number format failed: " + e.getMessage(), e);
  return String.valueOf(numberObject); // fallback
}

Prevention

When it happens

Trigger: Calling getString() on a TYPE_NUMBER value when DecimalFormat.format fails — e.g. a NaN/Infinity value with certain masks, an invalid or incompatible conversion mask, or a broken DecimalFormat created from a bad format string/locale.

Common situations: Conversion masks with illegal characters; formatting Double.NaN or Infinity with a decimal mask; mask mismatch between this value meta and storageMetadata triggering the 50-fraction-digit path; locale changes making the mask invalid.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/pentaho/di/core/row/value/ValueMetaBase.java:999

        if ( length < emptyPaddedStrings.length ) {
          return emptyPaddedStrings[length];
        } else {
          return Const.rightPad( "", length );
        }
      }
    }

    try {
      DecimalFormat format = getDecimalFormat( false );

      // When conversion masks are different, we must ensure the number precision is not lost
      if ( this.conversionMask != null && storageMetadata != null
              && !this.conversionMask.equals( storageMetadata.getConversionMask() ) ) {
        format.setMaximumFractionDigits( 50 );
      }
      return format.format( number );
    } catch ( Exception e ) {
      throw new KettleValueException( toString() + " : couldn't convert Number to String ", e );
    }
  }

  protected synchronized String convertNumberToCompatibleString( Double number ) throws KettleValueException {
    if ( number == null ) {
      return null;
    }
    return Double.toString( number );
  }

  protected synchronized Double convertStringToNumber( String string ) throws KettleValueException {
    string = Const.trimToType( string, getTrimType() ); // see if trimming needs
    // to be performed before
    // conversion

    if ( Utils.isEmpty( string ) ) {
      return null;
    }

View on GitHub (pinned to f3058517a1)