pentaho/pentaho-kettle · error · SAXException

Invalid Transformation - Missing…

Error message

Invalid Transformation - Missing transformation_configuration tag

What it means

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.

Solutions

  1. Post the full transformation_configuration export XML (as generated by the export endpoint), not a plain .ktr.
  2. Verify the request body actually contains XML (check for empty body or HTML error responses from upstream).
  3. Validate the root element locally before uploading: parse and check documentElement name equals 'transformation_configuration'.
  4. Ensure the client sets Content-Type application/xml and sends the complete body.

Example fix

// before
byte[] body = Files.readAllBytes(Paths.get("trans.ktr")); // root: <transformation>
post("/kettle/registerTrans/", body);
// after
byte[] body = Files.readAllBytes(Paths.get("transformation_configuration.xml")); // root: <transformation_configuration>
post("/kettle/registerTrans/", body, "application/xml");
Defensive patterns

Strategy: validation

Validate before calling

import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.ByteArrayInputStream;
boolean isTransformationConfiguration(byte[] body) throws Exception {
  DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
  df.setFeature("http://xml.org/sax/features/external-general-entities", false);
  Document doc = df.newDocumentBuilder().parse(new ByteArrayInputStream(body));
  return doc.getDocumentElement().getNodeName().equals("transformation_configuration");
}

Try / catch

try {
  post("/kettle/registerTrans/", body, "application/xml");
} catch (BadRequestException e) {
  // server rejected: body root is not transformation_configuration
  log.error("Upload must be a transformation configuration export, not a plain .ktr");
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at engine/src/main/java/org/pentaho/di/www/RegisterTransServlet.java:82

      return new WebResult( WebResult.STRING_OK, message, trans.getContainerObjectId() );
    } catch ( KettleXMLException | SAXException ex ) {
      response.setStatus( HttpServletResponse.SC_BAD_REQUEST );
      return new WebResult( WebResult.STRING_ERROR, ex.getMessage(), "" );
    } catch ( Exception ex ) {
      response.setStatus( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
      return new WebResult( WebResult.STRING_ERROR, ex.getMessage(), "" );
    }
  }

  public void validateTransformation( InputStream is ) throws IOException, ParserConfigurationException, SAXException,
    XPathExpressionException {
    DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
    df.setFeature( "http://xml.org/sax/features/external-general-entities", false );
    df.setFeature( "http://xml.org/sax/features/external-parameter-entities", false );
    DocumentBuilder builder = df.newDocumentBuilder();
    Document doc = builder.parse( is );
    if ( !doc.getDocumentElement().getNodeName().equals( "transformation_configuration" ) ) {
      throw new SAXException( "Invalid Transformation - Missing transformation_configuration tag" );
    }
    XPath xPath = XPathFactory.newInstance().newXPath();
    Node node = (Node) xPath.evaluate( "/transformation_configuration/transformation/info/name", doc, XPathConstants.NODE );
    if ( node == null  || node.getChildNodes().getLength() > 1 || !( node.getFirstChild() instanceof DeferredTextImpl ) ) {
      throw new SAXException( "Invalid Transformation Name" );
    }
  }

}

View on GitHub (pinned to f3058517a1)