{"record":{"id":"db8ab3196d9e3fc1","repo":"pentaho/pentaho-kettle","slug":"operation-repository-is-read-only","errorCode":null,"errorMessage":"{operation} : repository is read-only","messagePattern":"(.+?) : 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":107,"sourceCode":"          if ( capabilities.isReadOnly() ) {\n            throw new KettleException( operation + \" : repository is read-only\" );\n          }\n          break;\n        case EXPLORE_DATABASE:\n          break;\n\n        case MODIFY_SLAVE_SERVER:\n        case MODIFY_CLUSTER_SCHEMA:\n        case MODIFY_PARTITION_SCHEMA:\n          if ( capabilities.isReadOnly() ) {\n            throw new KettleException( operation + \" : repository is read-only\" );\n          }\n          break;\n        case DELETE_SLAVE_SERVER:\n        case DELETE_CLUSTER_SCHEMA:\n        case DELETE_PARTITION_SCHEMA:\n          if ( capabilities.isReadOnly() ) {\n            throw new KettleException( operation + \" : repository is read-only\" );\n          }\n          break;\n\n        default:\n          throw new KettleException( \"Operation [\" + operation + \"] is unknown to the security handler.\" );\n\n      }\n    }\n  }\n\n  public boolean isReadOnly() {\n    return capabilities.isReadOnly();\n  }\n\n  public boolean isLockingPossible() {\n    return capabilities.supportsLocking();\n  }\n","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/repository/filerep/KettleFileRepositorySecurityProvider.java#L89-L125","documentation":"This throw covers the DELETE_SLAVE_SERVER, DELETE_CLUSTER_SCHEMA and DELETE_PARTITION_SCHEMA operations in validateAction: deleting these shared cluster objects is refused when the file repository is read-only. The operation name is interpolated into the message.","triggerScenarios":"KettleFileRepository.deleteSlaveServer / deleteClusterSchema / deletePartitionSchema (or the matching RepositorySecurityProvider DELETE_* operation) on a repository whose capabilities say read-only.","commonSituations":"Pruning unused cluster/slave definitions from a repository on a read-only network share; automated cleanup scripts against a locked-down repository.","solutions":["Open the repository in read-write mode before deleting these objects.","Repair filesystem/mount permissions on the repository directory.","Perform cleanup during a maintenance window using a writable connection.","Remove the definition files directly on the repository host if API deletion is not possible."],"exampleFix":"// before\nreadOnlyRepo.deleteSlaveServer(slave.getObjectId());\n// after\nrepoMeta.setReadOnly(false);\nrepo.connect();\nrepo.deleteSlaveServer(slave.getObjectId());","handlingStrategy":"try-catch","validationCode":"if (repo.getSecurityProvider().isReadOnly()) {\n  throw new IllegalStateException(\"Repository read-only; cannot delete slave/cluster/partition\");\n}","typeGuard":"boolean deletable = repo != null && !repo.getSecurityProvider().isReadOnly();","tryCatchPattern":"try {\n  repo.deleteClusterSchema(id);\n} catch (KettleException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"repository is read-only\")) {\n    // reopen read-write or log and skip deletion\n  } else { throw e; }\n}","preventionTips":["Always probe isReadOnly() before DELETE_* repository operations.","Use dedicated writable maintenance connections for repository cleanup.","Document read-only connections as browse-only in team workflows."],"tags":["repository","read-only","delete"],"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"}