{"record":{"id":"c93e3963bb050d3a","repo":"pentaho/pentaho-kettle","slug":"invalid-transformation-name","errorCode":null,"errorMessage":"Invalid Transformation Name","messagePattern":"Invalid Transformation Name","errorType":"http","errorClass":"SAXException","httpStatus":500,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/www/AddTransServlet.java","lineNumber":356,"sourceCode":"\n  public String getContextPath() {\n    return CONTEXT_PATH;\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","sourceCodeStart":338,"sourceCodeEnd":360,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/www/AddTransServlet.java#L338-L360","documentation":"AddTransServlet.validateTransformation throws this SAXException when the /transformation_configuration/transformation/info/name node is missing, has more than one child node, or its first child is not a plain text node. The servlet rejects transformation names that are absent, duplicated, or contain nested markup rather than simple text.","triggerScenarios":"POSTed XML lacks an <info><name> element under <transformation>, contains multiple/duplicated name nodes, or embeds elements/CDATA/entities inside <name> instead of plain text.","commonSituations":"Hand-built XML for the Carte addTrans API omitting the info/name element; templating engines injecting extra nodes or escaping into <name>; a transformation name with XML special characters (&, <) that got expanded into nested nodes; copy-paste of config producing duplicate <name> tags.","solutions":["Ensure exactly one <info><name> element containing plain text exists under <transformation>.","Escape XML special characters in the transformation name (& → &amp;, < → &lt;).","Remove duplicate <name> nodes — validate the XML structure with an XML parser/linter before POSTing.","Remove any nested elements or comments inside <name>; keep it a simple text value."],"exampleFix":"// before: invalid name content\n<info><name>etl &amp; load<env>prod</env></name></info>\n// after: single plain-text name\n<info><name>etl &amp; load</name></info>","handlingStrategy":"validation","validationCode":"DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();\nDocument doc = df.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));\nNodeList names = doc.getElementsByTagName(\"name\");\nif (names.getLength() != 1 || names.item(0).getChildNodes().getLength() != 1\n    || names.item(0).getFirstChild().getNodeType() != Node.TEXT_NODE) {\n    throw new IllegalArgumentException(\"Exactly one plain-text <name> required\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    postToAddTrans(xmlBody);\n} catch (SAXException e) {\n    if (e.getMessage().equals(\"Invalid Transformation Name\")) { /* fix <info><name> content */ }\n    throw e;\n}","preventionTips":["Use an XML-escaping templating function for transformation names.","Keep <info><name> as a single plain-text element — no nested tags or comments.","Validate generated request XML with a parser before POSTing to Carte."],"tags":["xml","servlet","validation","carte","rest"],"backgroundTag":"invalid-identifier-format","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"}