{"record":{"id":"45d67893eb596e44","repo":"theonedev/onedev","slug":"refupdateexception","errorCode":null,"errorMessage":"RefUpdateException","messagePattern":"RefUpdateException","errorType":"exception","errorClass":"RefUpdateException","httpStatus":null,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/git/GitUtils.java","lineNumber":687,"sourceCode":"\t}\n\n\tpublic static RefUpdate getRefUpdate(Repository repository, String refName) {\n\t\ttry {\n\t\t\treturn repository.updateRef(refName);\n\t\t} catch (IOException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\tpublic static void updateRef(RefUpdate refUpdate) {\n\t\ttry {\n\t\t\tRefUpdate.Result result = refUpdate.forceUpdate();\n\t\t\tif (result == RefUpdate.Result.LOCK_FAILURE && refUpdate.getExpectedOldObjectId() != null\n\t\t\t\t\t&& !refUpdate.getExpectedOldObjectId().equals(refUpdate.getOldObjectId())) {\n\t\t\t\tthrow new ObsoleteCommitException(refUpdate.getOldObjectId());\n\t\t\t} else if (result != RefUpdate.Result.FAST_FORWARD && result != RefUpdate.Result.FORCED\n\t\t\t\t\t&& result != RefUpdate.Result.NEW && result != RefUpdate.Result.NO_CHANGE) {\n\t\t\t\tthrow new RefUpdateException(result);\n\t\t\t}\n\t\t} catch (IOException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t}\n\n\tpublic static void deleteRef(RefUpdate refUpdate) {\n\t\ttry {\n\t\t\trefUpdate.setForceUpdate(true);\n\t\t\tRefUpdate.Result result = refUpdate.delete();\n\t\t\tif (result == RefUpdate.Result.LOCK_FAILURE && refUpdate.getExpectedOldObjectId() != null\n\t\t\t\t\t&& !refUpdate.getExpectedOldObjectId().equals(refUpdate.getOldObjectId())) {\n\t\t\t\tthrow new ObsoleteCommitException(refUpdate.getOldObjectId());\n\t\t\t} else if (result != RefUpdate.Result.FAST_FORWARD && result != RefUpdate.Result.FORCED\n\t\t\t\t\t&& result != RefUpdate.Result.NEW && result != RefUpdate.Result.NO_CHANGE) {\n\t\t\t\tthrow new RefUpdateException(result);\n\t\t\t}\n\t\t} catch (IOException e) {","sourceCodeStart":669,"sourceCodeEnd":705,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/git/GitUtils.java#L669-L705","documentation":"GitUtils.updateRef (public static) wraps JGit RefUpdate.forceUpdate(). After the update it checks the RefUpdate.Result: if the lock failed because the ref moved since the expected old object id was set, it throws ObsoleteCommitException; any other result that is not FAST_FORWARD, FORCED, NEW or NO_CHANGE throws RefUpdateException carrying the JGit result name (e.g. REJECTED, IO_FAILURE). OneDev throws this because the ref update was not applied.","triggerScenarios":"Calling GitUtils.updateRef(refUpdate) when forceUpdate() returns a result such as REJECTED_NON_FAST_FORWARD / REJECTED_CURRENT_BRANCH / REJECTED / IO_FAILURE, i.e. the ref update could not be forced. Typical: trying to update HEAD of a branch with concurrent pushes, updating a ref that is currently checked out, or underlying filesystem/refdb IO failure.","commonSituations":"Push rejected because branch changed concurrently; attempting to overwrite a protected branch; a hook or another process holding the ref; disk/permissions problems in .git producing IO_FAILURE.","solutions":["Read RefUpdateException.getResult() and map the JGit result (REJECTED*, IO_FAILURE) to a concrete cause","Re-fetch the ref, rebuild the RefUpdate with the latest old object id, and retry (handle ObsoleteCommitException for the racing case)","If REJECTED_CURRENT_BRANCH, switch the update to a non-checked-out ref or update the target branch instead","Check filesystem permissions/disk for IO_FAILURE results"],"exampleFix":"// before\nRefUpdate ru = repo.updateRef(\"refs/heads/main\");\nru.setExpectedOldObjectId(oldId);\nru.setNewObjectId(newId);\nGitUtils.updateRef(ru); // throws RefUpdateException: REJECTED\n// after\nru.setExpectedOldObjectId(repo.exactRef(\"refs/heads/main\").getObjectId()); // re-read latest\nGitUtils.updateRef(ru);","handlingStrategy":"try-catch","validationCode":"// pre-check before update\nRef ref = repo.exactRef(refName);\nru.setExpectedOldObjectId(ref != null ? ref.getObjectId() : null);\nru.setForceUpdate(true);","typeGuard":"boolean isUpdatable(RefUpdate.Result r) {\n  return r == RefUpdate.Result.FAST_FORWARD || r == RefUpdate.Result.FORCED\n      || r == RefUpdate.Result.NEW || r == RefUpdate.Result.NO_CHANGE;\n}","tryCatchPattern":"try {\n  GitUtils.updateRef(ru);\n} catch (ObsoleteCommitException e) {\n  // re-read ref and retry\n} catch (RefUpdateException e) {\n  switch (e.getResult()) {\n    case REJECTED_CURRENT_BRANCH: /* switch branch/bare repo */ break;\n    case IO_FAILURE: /* check permissions/disk */ break;\n    default: /* map result to user message */ }\n}","preventionTips":["Always set expectedOldObjectId from a freshly read ref to get ObsoleteCommitException instead of silent races","Serialize ref mutations per ref (locks/queues) to avoid concurrent pushes","Check result name in RefUpdateException.getResult() before retrying"],"tags":["git","ref-update","jgit","concurrency"],"backgroundTag":"git-command-failed","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"}