pentaho/pentaho-kettle · error · KettleException
Unable to save repository element [ + repositoryElement + ]…
Error message
Unable to save repository element [ + repositoryElement + ] to XML file : + calcFilename( repositoryElement )
What it means
This wraps any unexpected exception thrown while persisting a repository element to its XML file in KettleFileRepository.save(). The original exception is chained; the message includes the element and the calculated target filename via calcFilename(). It is the generic save-failure path covering IO errors, VFS problems, and serialization bugs.
Solutions
- Inspect the chained cause 'Caused by' — it identifies the real IO/serialization problem.
- Verify the file repository base directory exists and is writable by the process user.
- Confirm calcFilename()'s computed path is valid (watch for illegal characters in element names).
- Check disk space and that the VFS provider for the repo URL is correctly configured.
Example fix
// before: base dir may not exist
KettleEnvironment.init();
repo.connect("admin", "admin");
// after: ensure base directory exists and is writable before saving
File base = new File(repoBaseDir);
if (!base.exists()) base.mkdirs();
if (!base.canWrite()) throw new IllegalStateException("Repo dir not writable: " + base);
repo.save(transMeta, null, null); Defensive patterns
Strategy: try-catch
Validate before calling
// verify repo base is writable before saving
if (!Files.isWritable(Paths.get(repoBaseDir))) throw new IllegalStateException("Repo not writable"); Try / catch
try {
repo.save(element, null, null);
} catch (KettleException e) {
if (e.getMessage().startsWith("Unable to save repository element")) {
log.error("Save failed for " + e.getCause(), e); // real cause is chained
} else { throw e; }
} Prevention
- Verify the file repo base directory exists and is writable at startup
- Watch for illegal characters in element names affecting calcFilename
- Monitor disk space on the repository volume
- Always inspect the chained 'Caused by' for the real IO error
When it happens
Trigger: Calling save() when the destination file cannot be written — path invalid or too long, missing directory, disk full, permission denied, VFS misconfiguration, or the element's getXML()/serialization throws.
Common situations: File repository base directory pointing to a nonexistent or read-only location; antivirus/file locks on Windows; running PDI as a user without write access to the repo folder; network-mounted repo path that dropped.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- ChangeFileEncoding.Error.CreatingFile
- ex.getMessage()
- Exporting jobs: Couldn't create file
- Exporting transformation: Couldn't create file
- GPLoadDataOutput.Exception" + e.getMessage()
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/78354cf9cb3cbee9.
Report an issue: GitHub.
Appendix: source
Thrown at engine/src/main/java/org/pentaho/di/repository/filerep/KettleFileRepository.java:347
// If so, we need to now remove the old file to prevent us from having multiple copies.
//
if ( repositoryElement.getObjectId() != null && !repositoryElement.getObjectId().equals( objectId ) ) {
delObject( repositoryElement.getObjectId() );
}
repositoryElement.setObjectId( objectId );
// Finally, see if there are external objects that need to be stored or updated in the MetaStore
//
if ( repositoryElement instanceof TransMeta ) {
( (TransMeta) repositoryElement ).saveMetaStoreObjects( this, metaStore );
}
if ( repositoryElement instanceof JobMeta ) {
( (JobMeta) repositoryElement ).saveMetaStoreObjects( this, metaStore );
}
} catch ( Exception e ) {
throw new KettleException( "Unable to save repository element ["
+ repositoryElement + "] to XML file : " + calcFilename( repositoryElement ), e );
}
}
@Override
public RepositoryDirectoryInterface createRepositoryDirectory( RepositoryDirectoryInterface parentDirectory,
String directoryPath ) throws KettleException {
String folder = calcDirectoryName( parentDirectory );
String newFolder = folder;
if ( folder.endsWith( "/" ) ) {
newFolder += directoryPath;
} else {
newFolder += "/" + directoryPath;
}
FileObject parent = KettleVFS.getInstance( DefaultBowl.getInstance() ).getFileObject( newFolder );
try {
parent.createFolder();View on GitHub (pinned to f3058517a1)