pentaho/pentaho-kettle · error · KettleException
Class [ + repositoryElement.getClass().getName() + ] needs…
Error message
Class [ + repositoryElement.getClass().getName() + ] needs to implement the XML Interface in order to save it to disk
What it means
KettleFileRepository.save() requires that any element written to the file repository either implements XMLInterface or SharedObjectInterface, because the file repository serializes elements to XML files on disk. If a repository element class implements neither, it cannot be persisted and a KettleException naming the offending class is thrown.
Solutions
- Make the element class implement XMLInterface (getXML(), loadXML()) so it can be serialized to disk.
- Alternatively implement SharedObjectInterface if the element is a shared object suitable for XML storage.
- Store non-XML-serializable objects in the metastore instead of the file repository.
- Check the named class in the message — it tells you exactly which custom type lacks the interface.
Example fix
// before
public class MyElement implements RepositoryElementInterface { ... }
// after
public class MyElement implements RepositoryElementInterface, XMLInterface {
public String getXML() { return xml; }
public void loadXML(Node node, ...) { ... }
} Defensive patterns
Strategy: type-guard
Validate before calling
boolean savable = element instanceof XMLInterface || element instanceof SharedObjectInterface;
Type guard
boolean canSaveToFileRepo(RepositoryElementInterface e) {
return e instanceof XMLInterface || e instanceof SharedObjectInterface;
} Try / catch
try {
repo.save(element, null, null);
} catch (KettleException e) {
if (e.getMessage().contains("needs to implement the XML Interface")) {
log.error("Custom element cannot go to file repo: " + element.getClass().getName());
} else { throw e; }
} Prevention
- Implement XMLInterface in any custom repository element meant for file repos
- Store non-XML-serializable metadata in the metastore instead
- Check the class name in the message to locate the offending type
When it happens
Trigger: Calling save(element, versionComment, monitor, parentId, used) with a custom or new RepositoryElementInterface implementation that doesn't implement XMLInterface (e.g. a custom plugin object added to a file repository).
Common situations: Custom PDI plugins storing their metadata objects into a file repository; newly introduced core element types used with an older file-repository code path; third-party extensions calling save() generically on arbitrary element types.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- AddSequenceMeta.Exception.ErrorLoadingStepInfo
- AnalyticQueryMeta.Exception.UnexpectedErrorInReadingStepInfo…
- AnalyticQueryMeta.Exception.UnableToLoadStepInfoFromXML
- AnalyticQueryMeta.Exception.UnableToSaveStepInfoToRepository
- ChangeFileEncodingMeta.Exception.UnableToReadStepInfo
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/119ebb9f5222f279.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/repository/filerep/KettleFileRepository.java:304
@Override
public void save( RepositoryElementInterface repositoryElement, String versionComment,
ProgressMonitorListener monitor, boolean overwrite ) throws KettleException {
// We always overwrite so no further changes necessary
save( repositoryElement, versionComment, monitor, null, overwrite );
}
@Override
public void save( RepositoryElementInterface repositoryElement, String versionComment, Calendar versionDate,
ProgressMonitorListener monitor, boolean overwrite ) throws KettleException {
save( repositoryElement, versionComment, monitor, null, overwrite );
}
public void save( RepositoryElementInterface repositoryElement, String versionComment,
ProgressMonitorListener monitor, ObjectId parentId, boolean used ) throws KettleException {
try {
if ( !( repositoryElement instanceof XMLInterface )
&& !( repositoryElement instanceof SharedObjectInterface ) ) {
throw new KettleException( "Class ["
+ repositoryElement.getClass().getName()
+ "] needs to implement the XML Interface in order to save it to disk" );
}
if ( !Utils.isEmpty( versionComment ) ) {
insertLogEntry( "Save repository element : " + repositoryElement.toString() + " : " + versionComment );
}
ObjectId objectId = new StringObjectId( calcObjectId( repositoryElement ) );
FileObject fileObject = getFileObject( repositoryElement );
String xml = ( (XMLInterface) repositoryElement ).getXML();
OutputStream os = KettleVFS.getInstance( DefaultBowl.getInstance() ).getOutputStream( fileObject, false );
os.write( xml.getBytes( Const.XML_ENCODING ) );
os.close();
View on GitHub (pinned to f3058517a1)