{"record":{"id":"78354cf9cb3cbee9","repo":"pentaho/pentaho-kettle","slug":"unable-to-save-repository-element-repositoryelement-to-xml","errorCode":null,"errorMessage":"Unable to save repository element [ + repositoryElement + ] to XML file : + calcFilename( repositoryElement )","messagePattern":"Unable to save repository element \\[ \\+ repositoryElement \\+ \\] to XML file : \\+ calcFilename\\( repositoryElement \\)","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/repository/filerep/KettleFileRepository.java","lineNumber":347,"sourceCode":"      // If so, we need to now remove the old file to prevent us from having multiple copies.\n      //\n      if ( repositoryElement.getObjectId() != null && !repositoryElement.getObjectId().equals( objectId ) ) {\n        delObject( repositoryElement.getObjectId() );\n      }\n\n      repositoryElement.setObjectId( objectId );\n\n      // Finally, see if there are external objects that need to be stored or updated in the MetaStore\n      //\n      if ( repositoryElement instanceof TransMeta ) {\n        ( (TransMeta) repositoryElement ).saveMetaStoreObjects( this, metaStore );\n      }\n      if ( repositoryElement instanceof JobMeta ) {\n        ( (JobMeta) repositoryElement ).saveMetaStoreObjects( this, metaStore );\n      }\n\n    } catch ( Exception e ) {\n      throw new KettleException( \"Unable to save repository element [\"\n        + repositoryElement + \"] to XML file : \" + calcFilename( repositoryElement ), e );\n    }\n  }\n\n  @Override\n  public RepositoryDirectoryInterface createRepositoryDirectory( RepositoryDirectoryInterface parentDirectory,\n    String directoryPath ) throws KettleException {\n    String folder = calcDirectoryName( parentDirectory );\n    String newFolder = folder;\n    if ( folder.endsWith( \"/\" ) ) {\n      newFolder += directoryPath;\n    } else {\n      newFolder += \"/\" + directoryPath;\n    }\n\n    FileObject parent = KettleVFS.getInstance( DefaultBowl.getInstance() ).getFileObject( newFolder );\n    try {\n      parent.createFolder();","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/repository/filerep/KettleFileRepository.java#L329-L365","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: base dir may not exist\nKettleEnvironment.init();\nrepo.connect(\"admin\", \"admin\");\n\n// after: ensure base directory exists and is writable before saving\nFile base = new File(repoBaseDir);\nif (!base.exists()) base.mkdirs();\nif (!base.canWrite()) throw new IllegalStateException(\"Repo dir not writable: \" + base);\nrepo.save(transMeta, null, null);","handlingStrategy":"try-catch","validationCode":"// verify repo base is writable before saving\nif (!Files.isWritable(Paths.get(repoBaseDir))) throw new IllegalStateException(\"Repo not writable\");","typeGuard":null,"tryCatchPattern":"try {\n  repo.save(element, null, null);\n} catch (KettleException e) {\n  if (e.getMessage().startsWith(\"Unable to save repository element\")) {\n    log.error(\"Save failed for \" + e.getCause(), e); // real cause is chained\n  } else { throw e; }\n}","preventionTips":["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"],"tags":["kettle","file-repository","file-write","io"],"backgroundTag":"file-write-failed","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"}