{"record":{"id":"8b6ff43566764f5b","repo":"pentaho/pentaho-kettle","slug":"modify-job-repository-is-read-only","errorCode":null,"errorMessage":"MODIFY_JOB : repository is read-only","messagePattern":"MODIFY_JOB : 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":70,"sourceCode":"          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          }\n          break;\n        case EXECUTE_JOB:\n          break;\n        case LOCK_JOB:\n          break;\n\n        case MODIFY_DATABASE:\n          if ( capabilities.isReadOnly() ) {\n            throw new KettleException( operation + \" : repository is read-only\" );\n          }\n          break;\n        case DELETE_DATABASE:","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/repository/filerep/KettleFileRepositorySecurityProvider.java#L52-L88","documentation":"KettleFileRepositorySecurityProvider.validateAction() throws this KettleException when a MODIFY_JOB operation is requested but the repository is flagged read-only. Like the transformation cases, the file repository enforces only the global read-only capability.","triggerScenarios":"Calling saveJob/update of a JobMeta through a KettleFileRepository connected with read-only capabilities.","commonSituations":"Repository opened read-only in Spoon (user believes they have write access); code reusing a shared read-only repository instance for job updates.","solutions":["Reconnect to the repository with read-only disabled","Set readOnly=false on the KettleFileRepositoryMeta before connecting","Guard job saves with capabilities.isReadOnly() checks","Persist job changes to an alternative writable repository when read-only mode is deliberate"],"exampleFix":"// before\nrepo.save(jobMeta, \"scheduled update\", null); // throws when read-only\n// after\nif (!repo.getRepositoryCapabilities().isReadOnly()) {\n  repo.save(jobMeta, \"scheduled update\", null);\n}","handlingStrategy":"validation","validationCode":"if (repo.getRepositoryCapabilities().isReadOnly()) {\n  throw new IllegalStateException(\"Repository is read-only; cannot modify jobs\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  repo.save(jobMeta, \"comment\", null);\n} catch (KettleException e) {\n  if (e.getMessage().contains(\"read-only\")) {\n    log.error(\"Job save blocked; reconnect with read-only disabled\");\n  }\n}","preventionTips":["Confirm connection mode before opening jobs for editing","Check capabilities.isReadOnly() before saving jobs","Avoid sharing a single read-only Repository instance across write paths"],"tags":["repository","read-only","security","jobs"],"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"}