{"record":{"id":"25c2d06d218557d3","repo":"theonedev/onedev","slug":"readonly-file-has-been-changed-during-upgrade","errorCode":null,"errorMessage":"Readonly file has been changed during upgrade: ","messagePattern":"Readonly file has been changed during upgrade: ","errorType":"exception","errorClass":"ExplicitException","httpStatus":null,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/commandhandler/Upgrade.java","lineNumber":605,"sourceCode":"\t\t\t\t\t\telse \n\t\t\t\t\t\t\tFileUtils.deleteDir(destChildFile);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (destFile.isFile())\n\t\t\t\t\tFileUtils.deleteFile(destFile);\n\t\t\t\tFileUtils.createDir(destFile);\n\t\t\t}\n\t\t\tfor (var srcChildFile: srcFile.listFiles())\n\t\t\t\trestoreProgramFiles(srcChildFile, new File(destFile, srcChildFile.getName()));\n\t\t} else try {\n\t\t\tif (destFile.isDirectory())\n\t\t\t\tFileUtils.deleteDir(destFile);\n\t\t\tif (destFile.exists()) {\n\t\t\t\tif (destFile.canWrite())\n\t\t\t\t\tFileUtils.copyFile(srcFile, destFile);\n\t\t\t\telse if (!Arrays.equals(FileUtils.readFileToByteArray(srcFile), FileUtils.readFileToByteArray(destFile)))\n\t\t\t\t\tthrow new ExplicitException(\"Readonly file has been changed during upgrade: \" + destFile.getAbsolutePath());\n\t\t\t} else {\n\t\t\t\tFileUtils.copyFile(srcFile, destFile);\n\t\t\t}\n\t\t} catch (IOException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\t\n\tprotected void updateProgramFiles(File upgradeDir, int oldAppDataVersion) {\n\t\tcleanAndCopy(new File(Bootstrap.installDir, \"3rdparty-licenses\"), new File(upgradeDir, \"3rdparty-licenses\"));\n\n\t\tFile siteServerScriptFile = new File(upgradeDir, \"bin/server.sh\");\n\t\tfor (File file: Bootstrap.getBinDir().listFiles()) {\n\t\t\tif (!file.getName().endsWith(\".pid\") && !file.getName().endsWith(\".status\")) {\n\t\t\t\ttry {\n\t\t\t\t\tString serverScript = null;\n\t\t\t\t\tif (file.getName().equals(\"server.sh\")) {\n\t\t\t\t\t\tserverScript = FileUtils.readFileToString(file, Charset.defaultCharset());","sourceCodeStart":587,"sourceCodeEnd":623,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/commandhandler/Upgrade.java#L587-L623","documentation":"During restoreProgramFiles in the upgrade handler, files marked read-only in the new program files are copied over existing ones only if the existing file is writable OR byte-identical. If a read-only destination file differs from the source, OneDev assumes local modifications and refuses to overwrite it, throwing this ExplicitException naming the file.","triggerScenarios":"Running an upgrade where the new version ships a read-only file (e.g. license, config template) whose content differs from the read-only file present in the current installation directory.","commonSituations":"Admins manually editing supposedly read-only files in the OneDev site directory, partial manual patches, or filesystem sync tools changing file contents between upgrades.","solutions":["Revert the named file to its original shipped content (or restore the whole previous program files from backup)","Make the file writable so the upgrade can overwrite it: chmod u+w <file>","Delete the changed file so the upgrade copies the fresh version in its place","Re-run the upgrade command after fixing the file"],"exampleFix":"// before\nchmod 444 site/conf/system.properties && edit it\n// after\nchmod u+w site/conf/system.properties && revert edits, then run upgrade","handlingStrategy":"validation","validationCode":"// compare readonly files before upgrading\nif (file.canWrite() == false && !Arrays.equals(readAll(src), readAll(dest))) revertFile(dest);","typeGuard":null,"tryCatchPattern":"try { upgrade(); } catch (ExplicitException e) { if (e.getMessage().startsWith(\"Readonly file has been changed\")) restoreOriginalFile(extractPath(e.getMessage())); }","preventionTips":["Never edit files in the OneDev site/program directories that ship read-only","Keep site customizations outside shipped program files","Snapshot the installation directory before upgrading","Diff your installation against a clean copy before upgrading"],"tags":["upgrade","file-conflict","readonly"],"backgroundTag":"file-modified-during-upgrade","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}