{"record":{"id":"595f2cdab499ad46","repo":"pentaho/pentaho-kettle","slug":"invalid-transformation-missing-transformation-configuration-595f2c","errorCode":null,"errorMessage":"Invalid Transformation - Missing transformation_configuration tag","messagePattern":"Invalid Transformation - Missing transformation_configuration tag","errorType":"http","errorClass":"SAXException","httpStatus":500,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/www/RegisterTransServlet.java","lineNumber":82,"sourceCode":"      return new WebResult( WebResult.STRING_OK, message, trans.getContainerObjectId() );\n    } catch ( KettleXMLException | SAXException ex ) {\n      response.setStatus( HttpServletResponse.SC_BAD_REQUEST );\n      return new WebResult( WebResult.STRING_ERROR, ex.getMessage(), \"\" );\n    } catch ( Exception ex ) {\n      response.setStatus( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );\n      return new WebResult( WebResult.STRING_ERROR, ex.getMessage(), \"\" );\n    }\n  }\n\n  public void validateTransformation( InputStream is ) throws IOException, ParserConfigurationException, SAXException,\n    XPathExpressionException {\n    DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();\n    df.setFeature( \"http://xml.org/sax/features/external-general-entities\", false );\n    df.setFeature( \"http://xml.org/sax/features/external-parameter-entities\", false );\n    DocumentBuilder builder = df.newDocumentBuilder();\n    Document doc = builder.parse( is );\n    if ( !doc.getDocumentElement().getNodeName().equals( \"transformation_configuration\" ) ) {\n      throw new SAXException( \"Invalid Transformation - Missing transformation_configuration tag\" );\n    }\n    XPath xPath = XPathFactory.newInstance().newXPath();\n    Node node = (Node) xPath.evaluate( \"/transformation_configuration/transformation/info/name\", doc, XPathConstants.NODE );\n    if ( node == null  || node.getChildNodes().getLength() > 1 || !( node.getFirstChild() instanceof DeferredTextImpl ) ) {\n      throw new SAXException( \"Invalid Transformation Name\" );\n    }\n  }\n\n}\n","sourceCodeStart":64,"sourceCodeEnd":92,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/www/RegisterTransServlet.java#L64-L92","documentation":"RegisterTransServlet.validateTransformation parses the posted XML and throws SAXException if the root element is not 'transformation_configuration'. The upload must be a full transformation configuration export, not a bare .ktr document.","triggerScenarios":"POST /kettle/registerTrans/ with a body whose XML root tag is something other than <transformation_configuration> — e.g. a plain <transformation> file, HTML error page, or truncated upload.","commonSituations":"Users posting a plain transformation.ktr instead of the configuration export produced by ExportTransServlet; a proxy returning an HTML error page that gets posted onward; empty/truncated request body.","solutions":["Post the full transformation_configuration export XML (as generated by the export endpoint), not a plain .ktr.","Verify the request body actually contains XML (check for empty body or HTML error responses from upstream).","Validate the root element locally before uploading: parse and check documentElement name equals 'transformation_configuration'.","Ensure the client sets Content-Type application/xml and sends the complete body."],"exampleFix":"// before\nbyte[] body = Files.readAllBytes(Paths.get(\"trans.ktr\")); // root: <transformation>\npost(\"/kettle/registerTrans/\", body);\n// after\nbyte[] body = Files.readAllBytes(Paths.get(\"transformation_configuration.xml\")); // root: <transformation_configuration>\npost(\"/kettle/registerTrans/\", body, \"application/xml\");","handlingStrategy":"validation","validationCode":"import javax.xml.parsers.*;\nimport org.w3c.dom.*;\nimport java.io.ByteArrayInputStream;\nboolean isTransformationConfiguration(byte[] body) throws Exception {\n  DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();\n  df.setFeature(\"http://xml.org/sax/features/external-general-entities\", false);\n  Document doc = df.newDocumentBuilder().parse(new ByteArrayInputStream(body));\n  return doc.getDocumentElement().getNodeName().equals(\"transformation_configuration\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  post(\"/kettle/registerTrans/\", body, \"application/xml\");\n} catch (BadRequestException e) {\n  // server rejected: body root is not transformation_configuration\n  log.error(\"Upload must be a transformation configuration export, not a plain .ktr\");\n}","preventionTips":["Always upload configuration exports (exported via the export servlet), never raw .ktr files.","Assert Content-Type is application/xml; reject HTML error pages before forwarding.","Check the body is non-empty and starts with '<?xml' before upload.","Validate root element name client-side pre-upload."],"tags":["xml","validation","servlet","upload"],"backgroundTag":"schema-validation-failed","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"}