{"record":{"id":"1adb91bd4e424408","repo":"pentaho/pentaho-kettle","slug":"delete-transformation-repository-is-read-only","errorCode":null,"errorMessage":"DELETE_TRANSFORMATION : repository is read-only","messagePattern":"DELETE_TRANSFORMATION : repository is read-only","errorType":"exception","errorClass":"KettleException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/repository/filerep/KettleFileRepositorySecurityProvider.java","lineNumber":58,"sourceCode":"\n  public RepositoryMeta getRepositoryMeta() {\n    return repositoryMeta;\n  }\n\n  public void validateAction( RepositoryOperation... operations ) throws KettleException, KettleSecurityException {\n\n    for ( RepositoryOperation operation : operations ) {\n      switch ( operation ) {\n        case READ_TRANSFORMATION:\n          break;\n        case MODIFY_TRANSFORMATION:\n          if ( capabilities.isReadOnly() ) {\n            throw new KettleException( operation + \" : repository is read-only\" );\n          }\n          break;\n        case DELETE_TRANSFORMATION:\n          if ( capabilities.isReadOnly() ) {\n            throw new KettleException( operation + \" : repository is read-only\" );\n          }\n          break;\n        case EXECUTE_TRANSFORMATION:\n          break;\n        case LOCK_TRANSFORMATION:\n          break;\n\n        case READ_JOB:\n          break;\n        case MODIFY_JOB:\n          if ( capabilities.isReadOnly() ) {\n            throw new KettleException( operation + \" : repository is read-only\" );\n          }\n          break;\n        case DELETE_JOB:\n          if ( capabilities.isReadOnly() ) {\n            throw new KettleException( operation + \" : repository is read-only\" );\n          }","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/repository/filerep/KettleFileRepositorySecurityProvider.java#L40-L76","documentation":"KettleFileRepositorySecurityProvider.validateAction() throws this KettleException when a DELETE_TRANSFORMATION operation is requested on a repository whose capabilities indicate isReadOnly() is true. This is the file repository's only access control: the read-only flag.","triggerScenarios":"Calling deleteTransformation (or any API that validates DELETE_TRANSFORMATION) against a read-only KettleFileRepository.","commonSituations":"User opens the repository in read-only mode intentionally but then tries to delete transformations; automated cleanup scripts pointing at a read-only repository connection.","solutions":["Reconnect with the read-only flag disabled before performing deletions","Remove read_only=Y from the repository metadata","Check capabilities.isReadOnly() before delete calls and skip/log instead","Use a separate writable connection for maintenance scripts"],"exampleFix":"// before\nrepo.deleteTransformation(transId); // fails when read-only\n// after\nif (!repo.getRepositoryCapabilities().isReadOnly()) {\n  repo.deleteTransformation(transId);\n}","handlingStrategy":"validation","validationCode":"if (repo.getRepositoryCapabilities().isReadOnly()) {\n  log.warn(\"Skipping delete; repository is read-only\");\n  return;\n}","typeGuard":null,"tryCatchPattern":"try {\n  repo.deleteTransformation(id);\n} catch (KettleException e) {\n  if (e.getMessage().contains(\"read-only\")) {\n    log.warn(\"Delete blocked: repository read-only\");\n  }\n}","preventionTips":["Gate all delete/maintenance scripts on a writable connection","Do not point cleanup jobs at read-only repository profiles","Surface the read-only capability in admin tooling"],"tags":["repository","read-only","delete","security"],"backgroundTag":"permission-denied","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"}