pentaho/pentaho-kettle · error · IOException

JobEntryXSDValidator.Error.DisallowedDocType (localized…

Error message

JobEntryXSDValidator.Error.DisallowedDocType (localized message)

What it means

When secure processing is on, the XSD validator disallows DOCTYPE declarations and installs an entity resolver that throws an IOException with the localized message JobEntryXSDValidator.Error.DisallowedDocType as soon as an external entity or DOCTYPE is encountered. This is a deliberate XXE-protection abort, not an incidental failure.

Solutions

  1. Remove the DOCTYPE/external entity declarations from the input XML
  2. Regenerate the XML without DTD references
  3. If DTDs are truly required and safe, disable the secure-processing option for this entry (understanding the XXE risk)
  4. Pre-scan files with a filter that rejects content starting with a DOCTYPE declaration

Example fix

// before: XML with DOCTYPE fails validation
<!DOCTYPE note SYSTEM "note.dtd">
<note>...</note>
// after: XML without DOCTYPE passes
<note>...</note>
Defensive patterns

Strategy: validation

Validate before calling

// reject DOCTYPE-bearing XML before validating
try ( BufferedReader r = Files.newBufferedReader( Paths.get( xmlFilename ), StandardCharsets.UTF_8 ) ) {
  String head = r.lines().limit( 5 ).collect( Collectors.joining( " " ) );
  if ( head.contains( "<!DOCTYPE" ) ) {
    throw new IllegalArgumentException( "DOCTYPE not allowed: " + xmlFilename );
  }
}

Try / catch

try {
  entry.execute( result, 0 );
} catch ( KettleException e ) {
  if ( e.getCause() instanceof IOException && e.getCause().getMessage().contains( "DisallowedDocType" ) ) {
    logError( "Input XML contains a DOCTYPE/external entity: " + e.getCause().getMessage() );
  }
  result.setResult( false );
}

Prevention

When it happens

Trigger: execute() validates an XML file that contains a DOCTYPE declaration or entity reference while the disallow-doctype-decl feature is enabled; the entity resolver throws IOException immediately.

Common situations: Legacy XML files generated with internal DTD subsets; XML feeds that use entity shortcuts; integrating old systems that emit DOCTYPE headers.

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/be618ee1d50425f4. Report an issue: GitHub.

Appendix: source

Thrown at plugins/xml/core/src/main/java/org/pentaho/di/job/entries/xsdvalidator/JobEntryXSDValidator.java:195

            XMLConstants.FEATURE_SECURE_PROCESSING, true);
          factorytXSDValidator_1.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);

          // Get XSD File
          File XSDFile = new File( KettleVFS.getFilename( xsdfile ) );
          Schema SchematXSD = factorytXSDValidator_1.newSchema( XSDFile );

          Validator xsdValidator = SchematXSD.newValidator();

          // Prevent against XML Entity Expansion (XEE) attacks.
          // https://www.owasp.org/index.php/XML_Security_Cheat_Sheet#XML_Entity_Expansion
          if ( !isAllowExternalEntities() ) {
            xsdValidator.setFeature( "http://apache.org/xml/features/disallow-doctype-decl", true );
            xsdValidator.setFeature( "http://xml.org/sax/features/external-general-entities", false );
            xsdValidator.setFeature( "http://xml.org/sax/features/external-parameter-entities", false );
            xsdValidator.setProperty( "http://apache.org/xml/properties/internal/entity-resolver",
              (XMLEntityResolver) xmlResourceIdentifier -> {
                String message = BaseMessages.getString( PKG, "JobEntryXSDValidator.Error.DisallowedDocType" );
                throw new IOException( message );
              } );
          }

          // Get XML File
          File xmlfiletXSDValidator_1 = new File( KettleVFS.getFilename( xmlfile ) );

          Source sourcetXSDValidator_1 = new StreamSource( xmlfiletXSDValidator_1 );

          xsdValidator.validate( sourcetXSDValidator_1 );

          // Everything is OK
          result.setResult( true );

        } else {

          if ( !xmlfile.exists() ) {
            logError( BaseMessages.getString( PKG, "JobEntryXSDValidator.FileDoesNotExist1.Label" ) + realxmlfilename
                + BaseMessages.getString( PKG, "JobEntryXSDValidator.FileDoesNotExist2.Label" ) );

View on GitHub (pinned to f3058517a1)