{"record":{"id":"85d58000a4068f39","repo":"pentaho/pentaho-kettle","slug":"mqttproducer-error-qos","errorCode":"MQTTProducer.Error.QOS","errorMessage":"MQTTProducer.Error.QOS","messagePattern":"MQTTProducer\\.Error\\.QOS","errorType":"exception","errorClass":"KettleStepException","httpStatus":null,"severity":"error","filePath":"plugins/streaming/impls/mqtt/src/main/java/org/pentaho/di/trans/step/mqtt/MQTTProducer.java","lineNumber":158,"sourceCode":"          .withServerUris( meta.serverUris )\n          .withMqttVersion( meta.mqttVersion )\n          .withAutomaticReconnect( meta.automaticReconnect )\n          .buildAndConnect();\n    } catch ( MqttException e ) {\n      connectionError.set( true );\n      throw new IllegalStateException( e );\n    } catch ( IllegalArgumentException iae ) {\n      connectionError.set( true );\n      throw iae;\n    }\n  }\n\n  private MqttMessage getMessage( Object[] row ) throws KettleStepException {\n    MqttMessage mqttMessage = new MqttMessage();\n    try {\n      mqttMessage.setQos( Integer.parseInt( meta.qos ) );\n    } catch ( NumberFormatException e ) {\n      throw new KettleStepException(\n        getString( PKG, \"MQTTProducer.Error.QOS\", meta.qos ) );\n    }\n    //noinspection ConstantConditions\n    mqttMessage.setPayload( getFieldData( row, meta.messageField )\n      .map( this::dataAsBytes )\n      .orElse( null ) ); //allow nulls to pass through\n    return mqttMessage;\n  }\n\n  private byte[] dataAsBytes( Object data ) {\n    if ( getInputRowMeta().searchValueMeta( meta.messageField ).isBinary() ) {\n      return (byte[]) data;\n    } else {\n      return Objects.toString( data ).getBytes( UTF_8 );\n    }\n  }\n\n  /**","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/plugins/streaming/impls/mqtt/src/main/java/org/pentaho/di/trans/step/mqtt/MQTTProducer.java#L140-L176","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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')."],"exampleFix":"// before (step config XML)\n<qos>${QOS_LEVEL}</qos>   // variable not set -> parses literal '${QOS_LEVEL}'\n// after\n<qos>1</qos>  // or ensure QOS_LEVEL is defined in kettle.properties: QOS_LEVEL=1","handlingStrategy":"validation","validationCode":"String qos = meta.qos == null ? \"\" : meta.qos.trim();\nint qosLevel;\ntry {\n  qosLevel = Integer.parseInt(qos);\n} catch (NumberFormatException e) {\n  throw new IllegalArgumentException(\"QoS must be an integer, got: '\" + qos + \"'\");\n}\nif (qosLevel < 0 || qosLevel > 2) {\n  throw new IllegalArgumentException(\"QoS must be 0, 1, or 2, got: \" + qosLevel);\n}","typeGuard":"boolean isValidQos(String s) {\n  if (s == null) return false;\n  try { int v = Integer.parseInt(s.trim()); return v >= 0 && v <= 2; }\n  catch (NumberFormatException e) { return false; }\n}","tryCatchPattern":"try {\n  trans.execute(null);\n} catch (KettleStepException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"MQTTProducer.Error.QOS\")) {\n    logError(\"Invalid MQTT QoS configured; fix the QoS field to 0, 1, or 2\");\n  } else {\n    throw e;\n  }\n}","preventionTips":["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."],"tags":["mqtt","configuration","number-format","kettle"],"backgroundTag":"invalid-config-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"}