pentaho/pentaho-kettle · error · KettleStepException
MQTTProducer.Error.QOS
MQTTProducer.Error.QOS
Error message
MQTTProducer.Error.QOS
What it means
The MQTT Producer step fails to parse the configured QoS (Quality of Service) level because meta.qos is not a valid integer. Paho's MqttMessage.setQos requires an int (0, 1, or 2), so any non-numeric text in the QoS field triggers a NumberFormatException, which is converted into a KettleStepException with the localized 'MQTTProducer.Error.QOS' message including the offending value.
Solutions
- Open the MQTT Producer step dialog and set the QoS field to a plain integer (0, 1, or 2).
- If the QoS uses a variable (${QOS}), verify the variable is defined (e.g. via kettle.properties or a Set Variables step) and resolves to a numeric value before the transformation runs.
- Inspect the saved transformation XML/ktr for the qos property and remove stray whitespace or non-numeric characters.
- If QoS is supplied downstream, validate/normalize it before invoking the step (e.g. coerce '2' vs ' 2').
Example fix
// before (step config XML)
<qos>${QOS_LEVEL}</qos> // variable not set -> parses literal '${QOS_LEVEL}'
// after
<qos>1</qos> // or ensure QOS_LEVEL is defined in kettle.properties: QOS_LEVEL=1 Defensive patterns
Strategy: validation
Validate before calling
String qos = meta.qos == null ? "" : meta.qos.trim();
int qosLevel;
try {
qosLevel = Integer.parseInt(qos);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("QoS must be an integer, got: '" + qos + "'");
}
if (qosLevel < 0 || qosLevel > 2) {
throw new IllegalArgumentException("QoS must be 0, 1, or 2, got: " + qosLevel);
} Type guard
boolean isValidQos(String s) {
if (s == null) return false;
try { int v = Integer.parseInt(s.trim()); return v >= 0 && v <= 2; }
catch (NumberFormatException e) { return false; }
} Try / catch
try {
trans.execute(null);
} catch (KettleStepException e) {
if (e.getMessage() != null && e.getMessage().contains("MQTTProducer.Error.QOS")) {
logError("Invalid MQTT QoS configured; fix the QoS field to 0, 1, or 2");
} else {
throw e;
}
} Prevention
- Always enter QoS as a bare integer (0, 1, 2) in the step dialog.
- If parameterizing QoS with a variable, define it in kettle.properties or a Set Variables step that runs before the transformation.
- Validate transformation metadata (including QoS) with a pre-run check in CI.
- Avoid copying QoS values from documents that may introduce whitespace or non-ASCII characters.
When it happens
Trigger: In MQTTProducer.processRow, getMessage(row) calls Integer.parseInt(meta.qos); any meta.qos value that is null, empty, or contains non-digit characters (e.g. 'qos1', '1 ', '0.5') throws this error.
Common situations: The QoS field was left blank in the step dialog; the value came from a variable like ${QOS} that was not defined at runtime, so the literal string is parsed; a user typed an invalid value or copied whitespace into the field; a metadata/kettle XML file was hand-edited with a non-numeric QoS.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- ScriptValuesMetaMod.Exception.NumberFormatException
- AccessInput.Exception.CouldnotFindField
- AccessInput.Log.NoField
- AddSequence.Exception.NoSpecifiedMethod
- At this time we don't support the use of multiple cluster…
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/85d58000a4068f39.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/streaming/impls/mqtt/src/main/java/org/pentaho/di/trans/step/mqtt/MQTTProducer.java:158
.withServerUris( meta.serverUris )
.withMqttVersion( meta.mqttVersion )
.withAutomaticReconnect( meta.automaticReconnect )
.buildAndConnect();
} catch ( MqttException e ) {
connectionError.set( true );
throw new IllegalStateException( e );
} catch ( IllegalArgumentException iae ) {
connectionError.set( true );
throw iae;
}
}
private MqttMessage getMessage( Object[] row ) throws KettleStepException {
MqttMessage mqttMessage = new MqttMessage();
try {
mqttMessage.setQos( Integer.parseInt( meta.qos ) );
} catch ( NumberFormatException e ) {
throw new KettleStepException(
getString( PKG, "MQTTProducer.Error.QOS", meta.qos ) );
}
//noinspection ConstantConditions
mqttMessage.setPayload( getFieldData( row, meta.messageField )
.map( this::dataAsBytes )
.orElse( null ) ); //allow nulls to pass through
return mqttMessage;
}
private byte[] dataAsBytes( Object data ) {
if ( getInputRowMeta().searchValueMeta( meta.messageField ).isBinary() ) {
return (byte[]) data;
} else {
return Objects.toString( data ).getBytes( UTF_8 );
}
}
/**View on GitHub (pinned to f3058517a1)